import Ember from 'ember';
import C from 'ui/utils/constants';

export default Ember.Controller.extend({
  github: Ember.inject.service(),
  endpoint: Ember.inject.service(),
  access: Ember.inject.service(),

  confirmDisable: false,
  errors: null,
  testing: false,
  saving: false,
  saved: true,
  error: null,
  originalModel: null,

  organizations: null,
  addUserInput: '',
  addOrgInput: '',

  createDisabled: function() {
    if ( this.get('isEnterprise') && !this.get('model.hostname') )
    {
      return true;
    }

    var id = (this.get('model.clientId')||'').trim();
    var secret = (this.get('model.clientSecret')||'').trim();
    return id.length < 20 ||secret.length < 40 || this.get('testing');
  }.property('model.{clientId,clientSecret,hostname}','testing','isEnterprise'),

  saveDisabled: Ember.computed.or('saving','saved'),
  isRestricted: Ember.computed.equal('model.accessMode','restricted'),

  wasRestricted: Ember.computed.equal('originalModel.accessMode','restricted'),
  wasRestrictedMsg: function() {
    var users = this.get('originalModel.allowedIdentities').filterBy('externalIdType',C.PROJECT.TYPE_GITHUB_USER).get('length');
    var orgs = this.get('originalModel.allowedIdentities').filterBy('externalIdType',C.PROJECT.TYPE_GITHUB_ORG).get('length');
    var enterprise = !!this.get('originalModel.hostname');

    var github = 'GitHub' + ( enterprise ? ' Enterprise' : '');

    var str = 'project members';
    if ( users )
    {
      str += (orgs ? ', ' : ' and ') +  users + ' ' + github + ' user' + (users === 1 ? '' : 's');
    }

    if ( orgs )
    {
      str += ' and ' + orgs + (users ? '' : ' ' + github) + ' organization' + ( orgs === 1 ? '' : 's');
    }

    return str;
  }.property('originalModel.allowedIdentities.[]','wasRestricted'),

  allowedActualIdentities: function() {
    return this.get('model.allowedIdentities').map((obj) => {
      obj.type = 'identity';
      return this.get('store').createRecord(obj);
    });
  }.property('model.allowedIdentities.[]'),

  wasShowing: false,
  showingAccessControl: function() {
    var show = this.get('wasShowing');
    var restricted = this.get('isRestricted');

    if ( restricted )
    {
      if ( this.get('allowedActualIdentities.length') > 1 )
      {
        show = true;
      }
      else if ( this.get('allowedActualIdentities.firstObject.id') !== this.get('access.identity.id') )
      {
        show = true;
      }
    }
    else
    {
      show = true;
    }


    this.set('wasShowing', show);
    return show;
  }.property('allowedActualIdentities.@each.id','isRestricted','wasShowing'),

  destinationUrl: function() {
    return window.location.origin+'/';
  }.property(),

  accessModeChanged: function() {
    this.set('saved',false);
  }.observes('accessMode'),

  isEnterprise: false,
  enterpriseDidChange: function() {
    if ( !this.get('isEnterprise') )
    {
      this.set('hostname', null);
    }
  }.observes('isEnterprise'),

  protocolChoices: [
    {label: 'https:// -- Requires a cert from a public CA', value: 'https://'},
    {label: 'http://', value: 'http://'},
  ],

  hostnameDidChange: function() {
    var cur = this.get('model.hostname')||'';
    var neu = cur.replace(/^https?:\/\//ig,'').replace(/\/.*$/,'');
    if ( cur !== neu )
    {
      this.set('hostname', neu);
    }
  }.observes('hostname'),

  actions: {
    test: function() {
      this.send('clearError');
      this.set('testing', true);

      var model = this.get('model');
      model.setProperties({
        'clientId': model.get('clientId').trim(),
        'clientSecret': model.get('clientSecret').trim(),
        'enabled': false, // It should already be, but just in case..
        'accessMode': 'unrestricted',
        'allowedIdentities': [],
      });

      // Send authenticate immediately so that the popup isn't blocked,
      // even though the config isn't necessarily saved yet...
      this.set('github.hostname', model.get('hostname'));
      this.set('github.clientId', model.get('clientId'));
      this.send('authenticate');

      model.save().catch(err => {
        this.set('testing', false);
        this.send('gotError', err);
      });
    },

    authenticate: function() {
      this.send('clearError');
      this.get('github').authorizeTest((err,code) => {
        if ( err )
        {
          this.send('gotError', err);
        }
        else
        {
          this.send('gotCode', code);
        }
      });
    },

    gotCode: function(code) {
      this.get('access').login(code).then(res => {
        var auth = JSON.parse(res.xhr.responseText);
        this.send('authenticationSucceeded', auth);
      }).catch(res => {
        // Github auth succeeded but didn't get back a token
        var err = JSON.parse(res.xhr.responseText);
        this.send('gotError', err);
      });
    },

    authenticationSucceeded: function(auth) {
      this.send('clearError');
      this.set('organizations', auth.orgs);

      var model = this.get('model').clone();
      model.setProperties({
        'enabled': true,
        'accessMode': 'restricted',
        'allowedIdentities': [auth.userIdentity],
      });

      var url = window.location.href;

      model.save().then(() => {
        // Set this to true so the token will be sent with the request
        this.set('access.enabled', true);

        return this.get('store').find('setting', C.SETTING.API_HOST).then((setting) => {
          if ( setting.get('value') )
          {
            this.send('waitAndRefresh', url);
          }
          else
          {
            // Default the api.host so the user won't have to set it in most cases
            setting.set('value', this.get('endpoint.host'));
            return setting.save().then(() => {
              this.send('waitAndRefresh', url);
            });
          }
        });
      }).catch((err) => {
        this.set('access.enabled', false);
        this.send('gotError', err);
      });
    },

    waitAndRefresh: function(url) {
      $('#loading-underlay, #loading-overlay').removeClass('hide').show();
      setTimeout(function() {
        window.location.href = url || window.location.href;
      }, 1000);
    },

    addAuthorized: function(data) {
      this.send('clearError');
      this.set('saved', false);
      this.get('model.allowedIdentities').pushObject(data);
    },

    githubNotFound: function(login) {
      this.send('showError',"User '"+ login + "' not found");
      this.send('removeUser',login);
    },

    removeIdentity: function(ident) {
      this.set('saved', false);
      this.get('model.allowedIdentities').removeObject(ident);
    },

    saveAuthorization: function() {
      this.send('clearError');

      if ( this.get('isRestricted') && !this.get('model.allowedIdentities.length') )
      {
        this.send('showError','Add at least one authorized user or organization');
        return;
      }

      this.set('saving', true);
      this.set('saved', false);

      var model = this.get('model');
      model.save().then(() => {
        this.get('originalModel').replaceWith(model);
        this.set('originalModel.allowedIdentities', this.get('model.allowedIdentities').slice());
        this.set('saved', true);
      }).catch((err) => {
        this.send('gotError', err);
      }).finally(() => {
        this.set('saving', false);
      });
    },

    promptDisable: function() {
      this.set('confirmDisable', true);
      Ember.run.later(this, function() {
        this.set('confirmDisable', false);
      }, 10000);
    },

    gotError: function(err) {
      if ( err.message )
      {
        this.send('showError', err.message + (err.detail? '('+err.detail+')' : ''));
      }
      else
      {
        this.send('showError', 'Error ('+err.status + ' - ' + err.code+')');
      }

      this.set('testing', false);
      this.set('saving', false);
    },

    showError: function(msg) {
      this.set('errors', [msg]);
      window.scrollY = 0;
    },

    clearError: function() {
      this.set('errors', null);
    },

    disable: function() {
      this.send('clearError');

      var model = this.get('model').clone();
      model.setProperties({
        'allowedIdentities': [],
        'accessMode': 'unrestricted',
        'enabled': false,
        'hostname': null,
        'clientSecret': '',
      });


      model.save().then(() => {
        this.get('access').clearSessionKeys();
        this.set('access.enabled',false);
        this.send('waitAndRefresh');
      }).catch((err) => {
        this.send('gotError', err);
      }).finally(() => {
        this.set('confirmDisable', false);
      });
    },

    showAccessControl: function() {
      this.set('wasShowing',true);
    },
  },
});
