
'use strict';

const Express = require('express');
const Github = require('octop');
const Semver = require('semver');
const Promisify = require('es6-promisify');
const BodyParser = require('body-parser');
const Moo = require('./moo');

const comp = require('./comp').comp;
const summary = require('./comp').summary;
const debug = require('debug')('moo:service');
const app = Express();
const token = process.env.GITHUB_ACCESS_TOKEN;
const github = new Github({'token': token});

app.use(BodyParser.json());
app.post('/hook/github/push', function (req, res) {
  let currVersion;
  let currBackwards;
  let currBranch;
  let tags;
  const compares = [];
  const body = req.body;
  if (body.action !== 'synchronize') {
    return res.end();
  }
  const repo = github.getRepo(
    body.repository.owner.login, body.repository.name);

  debug('getting tags...');
  Promisify(repo.getTags)()
  .then(function (data) {
    tags = data;
    currBranch = body.pull_request.head.ref;

    debug('getting package.json')
    return Promisify(repo.read)(currBranch, 'package.json');
  })
  .then(function (data) {
    data = JSON.parse(data);
    currVersion = data.version;
    currBackwards = data.backwards;
    tags = refineTags(tags);
    
    debug('comparing tree...');
    console.log(tags);
    return compare(0);
  })
  .then(function (idx) {
    res.end();

    let prog;
    let text = '> this message is generated by SeanBot\n\n';
    const num = body.number;
    const username = body.pull_request.user.login;
    const backwards = tags[idx].version;
    
    // check if current backwards equal to setup backwards value.
    if (currBackwards === backwards) {
      prog = Promisify(repo.removeLabel)(num, 'compatible');
    } else {
      if (currBackwards > backwards) {
        text += `Current backwards: ${currBackwards},` +
          `suggest to use backwards: ${backwards}. `;
      } else {
        // if current is less than backwards, should notify
        // pr-or update it
        // TODO(Yorkie): create a status for this case?
        text += `Backwards is expired at ${currBackwards}, ` +
          `please @${username} upgrade it to ${backwards}. `;
      }
      // build summary
      const latest = tags[0].ref;
      const r = comp(compares[0].value, compares[idx + 1].value);
      console.log(r, idx, compares[0].value, compares[2].value);
      text += summary(r, backwards, latest, body.repository.html_url);
      console.log(text);
      // connect to Github, then comment and label
      // prog = Promise.all([
      //   Promisify(repo.comment)(num, text),
      //   Promisify(repo.addLabels)(num, 'compatible')
      // ]);
    }
    // prog.then(function () {
    //   console.log('commented done');
    // });
  })
  .catch(function (err) {
    if (err) {
      console.error(err && err.stack);
    }
    res.status(500).end(err);
  });

  function compare (i, ifReturn) {
    const tag = tags[i];
    return getMoo(tag.ref)
    .then(function (data) {
      compares[i] = {
        version: tag.version,
        value: data
      };
      if (i === 0) return compare(1);
      if (ifReturn) return i - 1;
      // start to compare
      const r = comp(compares[i - 1].value, compares[i].value);
      console.log(r);
      if (r.deletion.length === 0 || r.modified.length === 0) {
        return compare(i + 1);
      } else {
        console.log('last version is', tag.version);
        return compare(i + 1, true);
      }
    });
  }

  function getMoo (ref) {
    return Promisify(repo.getTree)(ref, true)
    .then(function (data) {
      return Promise.all(
        data.filter(function (item) { 
          return item && /^common\/models\/(.*)\.js$/.test(item.path); 
        }).map(function (item) {
          const read = Promisify(repo.read);
          return read(ref, item.path).then(Moo);
        })
      );
    });
  }

  function refineTags (tags) {
    return tags.map(function (item) {
      const m = /^refs\/tags\/v(.\..\..)$/.exec(item && item.ref);
      if (m && m[1]) {
        return { 
          ref: item.ref, 
          version: m[1] 
        };
      } else {
        return null;
      }
    }).filter(function (item) {
      return item && item.version && 
        Semver.valid(item.version) &&
        Semver.lt(item.version, currVersion);
    })
    .concat(
      {
        ref: currBranch,
        version: currVersion
      }
    )
    .reverse();
  }

});

if (process.env.NODE_ENV === 'test') {
  module.exports = app;
} else {
  const port = process.env.PORT || 8001;
  app.listen(port, function () {
    debug('Moo service is up on ' + port);
  });
}

@@ -3245,16 +3245,46 @@
 le.log(r
+, compares%5Bi - 1%5D, compares%5Bi%5D
 );%0A     

update deps