'use strict';

var _regenerator = require('babel-runtime/regenerator');

var _regenerator2 = _interopRequireDefault(_regenerator);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var Router = require('koa-router');
var MemoryFile = require('../components/MemoryFile');
var Fs = require('fs');
var Logger = require('../components/Logger');
var protocols = {
  'http:': require('http'),
  'https:': require('https')
};
var Path = require('path');
var URL = require('url');
var Config = require('../components/Config');
var Builder = require('../components/Builder');
var bundleWrapper = require('../util/BundleWrapper');
var MessageBus = require('../components/MessageBus');
var DeviceManager = require('../components/DeviceManager');
var httpRouter = Router();

function getRemote(url) {
  return new Promise(function (resolve, reject) {
    var urlObj = URL.parse(url);
    (protocols[urlObj.protocol] || protocols['http:']).get({
      hostname: urlObj.hostname,
      port: urlObj.port,
      path: urlObj.path,
      method: 'GET',
      headers: {
        'User-Agent': 'Weex/1.0.0'
      }
    }, function (res) {
      var chunks = [];
      res.on('data', function (chunk) {
        chunks.push(chunk);
      });
      res.on('end', function () {
        resolve(Buffer.concat(chunks).toString());
        chunks = null;
      });
    }).on('error', function (e) {
      reject(e);
    });
  });
}
var rSourceMapDetector = /\.map$/;
httpRouter.get('/source/*', /*#__PURE__*/_regenerator2.default.mark(function _callee(next) {
  var path, content, query, file, _content;

  return _regenerator2.default.wrap(function _callee$(_context) {
    while (1) {
      switch (_context.prev = _context.next) {
        case 0:
          path = this.params[0];

          if (!rSourceMapDetector.test(path)) {
            _context.next = 8;
            break;
          }

          _context.next = 4;
          return getRemote('http://' + path);

        case 4:
          content = _context.sent;

          if (!content) {
            this.response.status = 404;
          } else {
            this.response.status = 200;
            this.set('Access-Control-Allow-Origin', '*');
            this.type = 'text/javascript';
            this.response.body = content;
          }
          _context.next = 25;
          break;

        case 8:
          query = this.request.url.split('?');

          query = query[1] ? '?' + query.slice(1).join('?') : '';
          file = MemoryFile.get(path + query);

          if (!file) {
            _context.next = 24;
            break;
          }

          this.response.status = 200;
          this.type = 'text/javascript';

          if (!(file.url && !Config.local)) {
            _context.next = 21;
            break;
          }

          _context.next = 17;
          return getRemote(file.url).catch(function (e) {
            Logger.error(e);
          });

        case 17:
          _content = _context.sent;

          if (!_content) {
            this.response.body = file.getContent();
          } else {
            this.response.body = bundleWrapper(_content, file.getUrl());
          }
          _context.next = 22;
          break;

        case 21:
          this.response.body = file.getContent();

        case 22:
          _context.next = 25;
          break;

        case 24:
          this.response.status = 404;

        case 25:
        case 'end':
          return _context.stop();
      }
    }
  }, _callee, this);
}));

function exists(file) {
  return new Promise(function (resolve, reject) {
    Fs.exists(file, function (flag) {
      resolve(flag);
    });
  });
}
var bundleDir = Path.join(__dirname, '../../frontend/', Config.bundleDir);
httpRouter.get('/' + Config.bundleDir + '/*', /*#__PURE__*/_regenerator2.default.mark(function _callee2(next) {
  var ext, dir, basename, bundle, map, we, vue, targetPath, _targetPath;

  return _regenerator2.default.wrap(function _callee2$(_context2) {
    while (1) {
      switch (_context2.prev = _context2.next) {
        case 0:
          ext = Path.extname(this.params[0]);

          if (!(ext === '.js' || ext === '.we' || ext === '.vue' || ext === '.map')) {
            _context2.next = 49;
            break;
          }

          dir = Path.dirname(this.params[0]);
          basename = Path.basename(this.params[0], ext);
          bundle = Path.join(bundleDir, dir, basename + '.js');
          map = Path.join(bundleDir, dir, basename + '.map');
          we = Path.join(Config.root || bundleDir, dir, basename + '.we');
          vue = Path.join(Config.root || bundleDir, dir, basename + '.vue');
          _context2.next = 10;
          return exists(bundle);

        case 10:
          if (!_context2.sent) {
            _context2.next = 16;
            break;
          }

          this.response.status = 200;
          this.type = 'text/javascript';
          this.response.body = Fs.createReadStream(bundle);
          _context2.next = 47;
          break;

        case 16:
          _context2.next = 18;
          return exists(vue);

        case 18:
          if (!_context2.sent) {
            _context2.next = 27;
            break;
          }

          _context2.next = 21;
          return Builder[Config.buildMode](vue, dir);

        case 21:
          targetPath = _context2.sent;

          this.response.status = 200;
          this.type = 'text/javascript';
          this.response.body = Fs.createReadStream(targetPath);
          _context2.next = 47;
          break;

        case 27:
          _context2.next = 29;
          return exists(we);

        case 29:
          if (!_context2.sent) {
            _context2.next = 38;
            break;
          }

          _context2.next = 32;
          return Builder[Config.buildMode](we, dir);

        case 32:
          _targetPath = _context2.sent;

          this.response.status = 200;
          this.type = 'text/javascript';
          this.response.body = Fs.createReadStream(_targetPath);
          _context2.next = 47;
          break;

        case 38:
          _context2.next = 40;
          return exists(map);

        case 40:
          if (!_context2.sent) {
            _context2.next = 46;
            break;
          }

          this.response.status = 200;
          this.type = 'text/javascript';
          this.response.body = Fs.createReadStream(map);
          _context2.next = 47;
          break;

        case 46:
          this.response.status = 404;

        case 47:
          _context2.next = 50;
          break;

        case 49:
          this.response.status = 404;

        case 50:
        case 'end':
          return _context2.stop();
      }
    }
  }, _callee2, this);
}));
var syncApiIndex = 0;
httpRouter.post('/syncApi', /*#__PURE__*/_regenerator2.default.mark(function _callee3() {
  var idx, payload, device, data;
  return _regenerator2.default.wrap(function _callee3$(_context3) {
    while (1) {
      switch (_context3.prev = _context3.next) {
        case 0:
          idx = syncApiIndex++;
          payload = this.request.body;
          device = DeviceManager.getDeviceBySessionId(payload.sessionId);

          if (!device) {
            _context3.next = 16;
            break;
          }

          delete payload.sessionId;
          payload.params.syncId = 100000 + idx;
          payload.id = 100000 + idx;
          device.send(payload);
          _context3.next = 10;
          return MessageBus.waitFor('sync.return.' + payload.id);

        case 10:
          data = _context3.sent;

          this.response.status = 200;
          this.type = 'application/json';
          this.response.body = JSON.stringify(data);
          _context3.next = 18;
          break;

        case 16:
          this.response.status = 500;
          this.response.body = 'device not found!';

        case 18:
        case 'end':
          return _context3.stop();
      }
    }
  }, _callee3, this);
}));
module.exports = httpRouter;