'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _regenerator;

function _load_regenerator() {
  return _regenerator = _interopRequireDefault(require('babel-runtime/regenerator'));
}

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

var getMergeResults = function () {
  var _ref3 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee4(consumer, modifiedFiles) {
    var _this = this;

    var tmp, conflictResultsP, conflictResults;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee4$(_context4) {
      while (1) {
        switch (_context4.prev = _context4.next) {
          case 0:
            tmp = new (_repositories || _load_repositories()).Tmp(consumer.scope);
            conflictResultsP = modifiedFiles.map(function () {
              var _ref4 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(modifiedFile) {
                var currentFilePathP, writeFile, baseFilePathP, otherFilePathP, _ref6, _ref7, otherFilePath, baseFilePath, currentFilePath, mergeFilesParams;

                return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
                  while (1) {
                    switch (_context3.prev = _context3.next) {
                      case 0:
                        currentFilePathP = tmp.save(modifiedFile.currentFile.contents);

                        writeFile = function () {
                          var _ref5 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(file) {
                            var content;
                            return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
                              while (1) {
                                switch (_context2.prev = _context2.next) {
                                  case 0:
                                    _context2.next = 2;
                                    return file.file.load(consumer.scope.objects);

                                  case 2:
                                    content = _context2.sent;
                                    return _context2.abrupt('return', tmp.save(content));

                                  case 4:
                                  case 'end':
                                    return _context2.stop();
                                }
                              }
                            }, _callee2, _this);
                          }));

                          return function writeFile(_x5) {
                            return _ref5.apply(this, arguments);
                          };
                        }();

                        baseFilePathP = tmp.save('');
                        otherFilePathP = writeFile(modifiedFile.otherFile);
                        _context3.next = 6;
                        return Promise.all([otherFilePathP, baseFilePathP, currentFilePathP]);

                      case 6:
                        _ref6 = _context3.sent;
                        _ref7 = _slicedToArray(_ref6, 3);
                        otherFilePath = _ref7[0];
                        baseFilePath = _ref7[1];
                        currentFilePath = _ref7[2];
                        mergeFilesParams = {
                          filePath: modifiedFile.filePath,
                          currentFile: {
                            label: modifiedFile.currentFile.version,
                            path: currentFilePath
                          },
                          baseFile: {
                            path: baseFilePath
                          },
                          otherFile: {
                            // $FlowFixMe
                            label: modifiedFile.otherFile.version,
                            path: otherFilePath
                          }
                        };
                        return _context3.abrupt('return', (0, (_mergeFiles || _load_mergeFiles()).default)(mergeFilesParams));

                      case 13:
                      case 'end':
                        return _context3.stop();
                    }
                  }
                }, _callee3, _this);
              }));

              return function (_x4) {
                return _ref4.apply(this, arguments);
              };
            }());
            _context4.prev = 2;
            _context4.next = 5;
            return Promise.all(conflictResultsP);

          case 5:
            conflictResults = _context4.sent;
            _context4.next = 8;
            return tmp.clear();

          case 8:
            return _context4.abrupt('return', conflictResults);

          case 11:
            _context4.prev = 11;
            _context4.t0 = _context4['catch'](2);
            _context4.next = 15;
            return tmp.clear();

          case 15:
            throw _context4.t0;

          case 16:
          case 'end':
            return _context4.stop();
        }
      }
    }, _callee4, this, [[2, 11]]);
  }));

  return function getMergeResults(_x2, _x3) {
    return _ref3.apply(this, arguments);
  };
}();

var _ramda;

function _load_ramda() {
  return _ramda = _interopRequireDefault(require('ramda'));
}

var _path;

function _load_path() {
  return _path = _interopRequireDefault(require('path'));
}

var _component;

function _load_component() {
  return _component = _interopRequireDefault(require('../../component'));
}

var _models;

function _load_models() {
  return _models = require('../../../scope/models');
}

var _;

function _load_() {
  return _ = require('../..');
}

var _utils;

function _load_utils() {
  return _utils = require('../../../utils');
}

var _sources;

function _load_sources() {
  return _sources = require('../../component/sources');
}

var _repositories;

function _load_repositories() {
  return _repositories = require('../../../scope/repositories');
}

var _mergeFiles;

function _load_mergeFiles() {
  return _mergeFiles = _interopRequireDefault(require('../../../utils/merge-files'));
}

var _generalError;

function _load_generalError() {
  return _generalError = _interopRequireDefault(require('../../../error/general-error'));
}

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

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

exports.default = function () {
  var _ref2 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee(_ref) {
    var consumer = _ref.consumer,
        otherComponent = _ref.otherComponent,
        otherVersion = _ref.otherVersion,
        currentComponent = _ref.currentComponent,
        currentVersion = _ref.currentVersion;
    var otherFiles, currentFiles, results, getFileResult, conflictResults;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            otherFiles = otherComponent.files;
            currentFiles = currentComponent.cloneFilesWithSharedDir();
            results = {
              addFiles: [],
              modifiedFiles: [],
              unModifiedFiles: [],
              overrideFiles: [],
              hasConflicts: false
            };

            getFileResult = function getFileResult(otherFile, currentFile) {
              var filePath = otherFile.relativePath;
              if (!currentFile) {
                results.addFiles.push({ filePath, otherFile });
                return;
              }
              var otherFileHash = otherFile.file.hash;
              var currentFileHash = (0, (_utils || _load_utils()).sha1)(currentFile.contents);
              if (otherFileHash === currentFileHash) {
                results.unModifiedFiles.push({ filePath, currentFile });
                return;
              }
              // it was changed in both, there is a chance for conflict
              currentFile.version = currentVersion;
              // $FlowFixMe it's a hack to pass the data, version is not a valid attribute.
              otherFile.version = otherVersion;
              results.modifiedFiles.push({ filePath, currentFile, otherFile, output: null, conflict: null });
            };

            otherFiles.forEach(function (otherFile) {
              var relativePath = (_path || _load_path()).default.normalize(otherFile.relativePath);
              var currentFile = currentFiles.find(function (file) {
                return file.relative === relativePath;
              });
              getFileResult(otherFile, currentFile);
            });

            if (!(_ramda || _load_ramda()).default.isEmpty(results.modifiedFiles)) {
              _context.next = 7;
              break;
            }

            return _context.abrupt('return', results);

          case 7:
            _context.next = 9;
            return getMergeResults(consumer, results.modifiedFiles);

          case 9:
            conflictResults = _context.sent;

            conflictResults.forEach(function (conflictResult) {
              var modifiedFile = results.modifiedFiles.find(function (file) {
                return file.filePath === conflictResult.filePath;
              });
              if (!modifiedFile) throw new (_generalError || _load_generalError()).default(`unable to find ${conflictResult.filePath} in modified files array`);
              modifiedFile.output = conflictResult.output;
              modifiedFile.conflict = conflictResult.conflict;
              if (conflictResult.conflict) results.hasConflicts = true;
            });

            return _context.abrupt('return', results);

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

  function twoWayMergeVersions(_x) {
    return _ref2.apply(this, arguments);
  }

  return twoWayMergeVersions;
}();