var fs = require('fs');
var path = require('path');

var loopbackCoreJs = path.resolve(__dirname, 'loopback-core.js');

try {
  var generator = require('..');
  var loopback = require('loopback');
} catch(err) {
  if (err.code === 'MODULE_NOT_FOUND' && fs.existsSync(loopbackCoreJs)) {
    console.log('Cannot load the generator, node_modules were not installed.');
    console.log('Ignoring the error since the output file is already there.');
    process.exit();
  }
  throw err;
}

console.log('Generating API docs for LoopBack built-in models.');

var app = loopback();

app.dataSource('db', { connector: 'memory', defaultForType: 'db' });

for (var key in loopback) {
  var model = loopback[key];
  if (!model) continue;
  if (model === loopback.Model || model === loopback.PersistedModel) continue;
  if (model.prototype instanceof loopback.PersistedModel) {
    app.model(model, { dataSource: 'db' });
    console.log('  added persisted model %s', key);
  } else if (model.prototype instanceof loopback.Model) {
    app.model(model);
    console.log('  added model %s', key);
  }
}

var script = generator.services(app, 'lbServices', '/api');

// Transform ngdoc comments and make them compatible with dox/strong-docs
script = script
  // Insert an empty line (serving as jsdoc description) before @ngdoc
  .replace(/^(\s+\*)( @ngdoc)/gm, '$1\n$1$2')
  // Remove module name from all names
  .replace(/\blbServices\./g, '')
  // Fix `## Example` sections
  .replace(/## Example/g, '**Example**')
  // Annotate Angular objects as jsdoc classes
  .replace(/^((\s+\*) @ngdoc object)/mg, '$1\n$2 @class')
  // Annonotate Angular methods as jsodc methods
  .replace(/^((\s+\*) @ngdoc method)/mg, '$1\n$2 @method')
  // Hide the top-level module description
  .replace(/^(\s+\*) @module.*$/mg, '$1 @private')
  // Change `Model#method` to `Model.method` in @name
  .replace(/^(\s+\* @name) ([^# \n]+)#([^# \n]+) *$/mg, '$1 $2.$3')
  // Change `Model#method` to `Model.method` in @link
  // Do not modify URLs with anchors, e.g. `http://foo/bar#anchor`
  .replace(/({@link [^\/# }\n]+)#([^# }\n]+)/g, '$1.$2');

fs.writeFileSync(loopbackCoreJs, script);

console.log('Done: %s', loopbackCoreJs);

@@ -638,16 +638,37 @@
 b' %7D);%0A%0A
+var modelNames = %5B%5D;%0A
 for (var
@@ -774,31 +774,169 @@
 odel
- %7C%7C model === loopback.
+) continue;%0A  if (model.prototype instanceof loopback.Model)%0A    modelNames.push(key);%0A%7D%0A%0AmodelNames.sort(function(l, r) %7B%0A  if (l === r) return 0;%0A  if (l === '
 Pers
@@ -941,34 +941,170 @@
 rsistedModel
+'
 ) 
-continue
+return -1;%0A  if (r === 'PersistedModel') return 1;%0A  return l %3C r ? -1 : 1;%0A%7D);%0A%0AmodelNames.forEach(function(key) %7B%0A  var model = loopback%5Bkey%5D
 ;%0A  if (mode
@@ -1375,17 +1375,19 @@
 y);%0A  %7D%0A
-
 %7D
+);
 %0A%0Avar sc

include PersistedModel, sort models