(function() {
  'use strict';
  window.Whisper = window.Whisper || {};

  var State = {
    IMPORTING: 1,
    COMPLETE: 2,
    LIGHT_COMPLETE: 3,
  };

  var IMPORT_STARTED = 'importStarted';
  var IMPORT_COMPLETE = 'importComplete';
  var IMPORT_LOCATION = 'importLocation';

  Whisper.Import = {
    isStarted: function() {
      return Boolean(storage.get(IMPORT_STARTED));
    },
    isComplete: function() {
      return Boolean(storage.get(IMPORT_COMPLETE));
    },
    isIncomplete: function() {
      return this.isStarted() && !this.isComplete();
    },
    start: function() {
      return storage.put(IMPORT_STARTED, true);
    },
    complete: function() {
      return storage.put(IMPORT_COMPLETE, true);
    },
    saveLocation: function(location) {
      return storage.put(IMPORT_LOCATION, location);
    },
    reset: function() {
      return Whisper.Database.clear();
    },
  };

  Whisper.ImportView = Whisper.View.extend({
    templateName: 'import-flow-template',
    className: 'full-screen-flow',
    events: {
      'click .choose': 'onImport',
      'click .restart': 'onRestart',
      'click .cancel': 'onCancel',
      'click .register': 'onRegister',
    },
    initialize: function() {
      if (Whisper.Import.isIncomplete()) {
        this.error = true;
      }

      this.render();
      this.pending = Promise.resolve();
    },
    render_attributes: function() {
      if (this.error) {
        return {
          isError: true,
          errorHeader: i18n('importErrorHeader'),
          errorMessage: i18n('importError'),
          chooseButton: i18n('importAgain'),
        };
      }

      var restartButton = i18n('importCompleteStartButton');
      var registerButton = i18n('importCompleteLinkButton');
      var step = 'step2';

      if (this.state === State.IMPORTING) {
        step = 'step3';
      } else if (this.state === State.COMPLETE) {
        registerButton = null;
        step = 'step4';
      } else if (this.state === State.LIGHT_COMPLETE) {
        restartButton = null;
        step = 'step4';
      }

      return {
        isStep2: step === 'step2',
        chooseHeader: i18n('loadDataHeader'),
        choose: i18n('loadDataDescription'),
        chooseButton: i18n('chooseDirectory'),

        isStep3: step === 'step3',
        importingHeader: i18n('importingHeader'),

        isStep4: step === 'step4',
        completeHeader: i18n('importCompleteHeader'),
        restartButton: restartButton,
        registerButton: registerButton,
      };
    },
    onRestart: function() {
      return window.restart();
    },
    onCancel: function() {
      this.trigger('cancel');
    },
    onImport: function() {
      window.Signal.Backup.getDirectoryForImport().then(
        function(directory) {
          this.doImport(directory);
        }.bind(this),
        function(error) {
          if (error.name !== 'ChooseError') {
            console.log(
              'Error choosing directory:',
              error && error.stack ? error.stack : error
            );
          }
        }
      );
    },
    onRegister: function() {
      // AppView listens for this, and opens up InstallView to the QR code step to
      //   finish setting this device up.
      this.trigger('light-import');
    },

    doImport: function(directory) {
      window.removeSetupMenuItems();

      this.error = null;
      this.state = State.IMPORTING;
      this.render();

      // Wait for prior database interaction to complete
      this.pending = this.pending
        .then(function() {
          // For resilience to interruption, clear database both before and on failure
          return Whisper.Import.reset();
        })
        .then(function() {
          return Promise.all([
            Whisper.Import.start(),
            window.Signal.Backup.importFromDirectory(directory),
          ]);
        })
        .then(
          function(results) {
            var importResult = results[1];

            // A full import changes so much we need a restart of the app
            if (importResult.fullImport) {
              return this.finishFullImport(directory);
            }

            // A light import just brings in contacts, groups, and messages. And we need a
            //   normal link to finish the process.
            return this.finishLightImport(directory);
          }.bind(this)
        )
        .catch(
          function(error) {
            console.log(
              'Error importing:',
              error && error.stack ? error.stack : error
            );

            this.error = error || new Error('Something went wrong!');
            this.state = null;
            this.render();

            return Whisper.Import.reset();
          }.bind(this)
        );
    },
    finishLightImport: function(directory) {
      ConversationController.reset();

      return ConversationController.load()
        .then(function() {
          return Promise.all([
            Whisper.Import.saveLocation(directory),
            Whisper.Import.complete(),
          ]);
        })
        .then(
          function() {
            this.state = State.LIGHT_COMPLETE;
            this.render();
          }.bind(this)
        );
    },
    finishFullImport: function(directory) {
      // Catching in-memory cache up with what's in indexeddb now...
      // NOTE: this fires storage.onready, listened to across the app. We'll restart
      //   to complete the install to start up cleanly with everything now in the DB.
      return storage
        .fetch()
        .then(function() {
          return Promise.all([
            // Clearing any migration-related state inherited from the Chrome App
            storage.remove('migrationState'),
            storage.remove('migrationEnabled'),
            storage.remove('migrationEverCompleted'),
            storage.remove('migrationStorageLocation'),

            Whisper.Import.saveLocation(directory),
            Whisper.Import.complete(),
          ]);
        })
        .then(
          function() {
            this.state = State.COMPLETE;
            this.render();
          }.bind(this)
        );
    },
  });
})();
