/* globals Twitch, i18n */

import Component from 'ember-component';
import computed from 'ember-computed';
import observer from 'ember-metal/observer';
import injectService from 'ember-service/inject';
import SendRouteActionMixin from 'web-client/mixins/send-route-action';

const TRANSLATED_URL = i18n('Your Community URL will be {{url}}');
const VALID_NAME_REGEX = /^[a-zA-Z]+[a-zA-Z0-9\.\-_~]*$/;
const MIN_NAME_LENGTH = 3;
const MAX_NAME_LENGTH = 25;

const REASON_TO_ERROR_MESSAGE = {
  account_too_young: 'Your account must be at least 90 days old to create a Community',
  community_name_exists: 'That name is unavailable',
  community_name_invalid: 'That name is unavailable',
  community_name_reserved: 'That name is unavailable',
  short_description_too_long: 'Your short description is too long',
  long_description_too_long: 'Your long description is too long',
  rules_too_long: 'Your rules are too long',
  own_too_many_communities: 'You cannot currently create more than 5 Communities',
  unverified_email: 'Your email must be verified to create a Community. Please verify your email at {{url}}',
  two_factor_not_enabled: 'You must have two-factor authentication enabled'
};

export default Component.extend(SendRouteActionMixin, {
  communities: injectService(),
  session: injectService(),
  tracking: injectService(),

  content: computed.alias('communities.communityInfo'),
  isLoading: false,
  editMode: false,
  createMode: false,
  agree: false,
  rollbackData: {},

  init: function() {
    this._super(...arguments);

    if (this.createMode) {
      this._trackCreate();
      let communityInfo = this.get('communities').getCommunityInfo();
      this.set('content', communityInfo);
    }
  },

  input: function() {
    this.set('isDirty', true);
  },

  communityUrl: computed('content.name', function() {
    return TRANSLATED_URL.replace('{{url}}', `https://www.twitch.tv/communities/${this.get('content.name')}`);
  }),

  canSaveCommunity: computed('isLoading', 'agree', 'content.name', 'isNameValid', 'content.summary', 'isOver160', 'content.description', 'content.rules', function() {
    if (this.get('createMode')) {
      if (!this.get('content.name') || !this.get('isNameValid') || !this.get('agree')) {
        return false;
      }
    }

    if (this.get('isLoading') || !this.get('content.summary') || this.get('isOver160') || !this.get('content.description') || !this.get('content.rules')) {
      return false;
    }

    return true;
  }),

  isNameValid: computed('content.name', function() {
    let name = this.get('content.name');
    let match = name.match(VALID_NAME_REGEX);
    if (!match || name.length < MIN_NAME_LENGTH || name.length > MAX_NAME_LENGTH) {
      return false;
    }
    return true;
  }),

  isOver160: computed.gt('shortDescriptionCharCount', 160),

  shortDescriptionCharCount: computed('content.summary', function() {
    let shortDescription = this.get('content.summary');
    return (shortDescription) ? shortDescription.length : 0;
  }),

  count160String: computed('shortDescriptionCharCount', function() {
    return `${this.get('shortDescriptionCharCount')}/160`;
  }),

  submitDisabled: computed.not('isDirty'),

  _rollbackOnExitEditMode: observer('editMode', function () {
    let content = this.get('content');
    if (this.get('editMode')) {
      for (let key in content) {
        this.set(`rollbackData.${key}`, content[key]);
      }
    } else {
      if (this.get('isDirty')) {
        // Rollback existing panels
        for (let key in content) {
          this.set(`content.${key}`, this.get(`rollbackData.${key}`));
        }
        this.set('isDirty', false);
      }
    }
  }),

  _trackCreate(name) {
    let event = 'community_create_initiate';
    let trackingObject = {
      login: this.get('session.userData.login'),
      is_subadmin: this.get('session.userData.is_admin'),
      is_admin: this.get('session.userData.is_staff')
    };
    if (name) {
      trackingObject.community_name = this.get('content.name');
      event = 'community_create_submit';
    }
    this.get('tracking').trackEvent({
      services: ['spade'],
      event: event,
      data: trackingObject
    });
  },

  _trackUpdate(editType) {
    let oldValue = this.get(`rollbackData.${editType}`);
    let newValue = this.get(`content.${editType}`);
    if (oldValue === newValue) {
      // Don't send tracking if values have not changed
      return;
    }
    let trackingObject = {
      community_id: this.get('communities.communityInfo._id'),
      community_name: this.get('communities.communityInfo.name'),
      login: this.get('session.userData.login'),
      is_owner: parseInt(this.get('communities.communityInfo.owner_id')) === this.get('session.userData.id'),
      is_subadmin: this.get('session.userData.is_admin'),
      is_admin: this.get('session.userData.is_staff'),
      edit_type: editType,
      old_value: oldValue,
      new_value: newValue
    };
    this.get('tracking').trackEvent({
      services: ['spade'],
      event: 'community_edit',
      data: trackingObject
    });
  },

  create() {
    this.set('isDirty', false);
    this._trackCreate(this.get('content.name'));
    this.set('isLoading', true);
    this.get('communities').createCommunity(this.get('content')).then((data) => {
      if (this.isDestroyed) { return; }
      let trackingObject = {
        community_id: data._id,
        community_name: this.get('content.name'),
        login: this.get('session.userData.login'),
        is_subadmin: this.get('session.userData.is_admin'),
        is_admin: this.get('session.userData.is_staff')
      };
      this.get('tracking').trackEvent({
        event: 'community_create_complete',
        data: trackingObject
      });
      this.sendRouteAction('handleCommunityClick', {'name': this.get('content.name')});
    }, e => {
      if (this.isDestroyed) { return; }
      this.set('isLoading', false);
      if (String(e.status)[0] === '4') { // Checking for a 4XX error code.
        let message = e.responseJSON.message;
        let reasonString = i18n(REASON_TO_ERROR_MESSAGE[message] || 'Oops, something went wrong');
        if (message === 'unverified_email') {
          reasonString.replace('{{url}}', '<a href="http://www.twitch.tv/settings" target=_blank rel=_noopener>http://www.twitch.tv/settings</a>');
        }
        Twitch.notify.error(reasonString);
        this.set('isDirty', true);
        return;
      }
    });
  },

  update() {
    if (!this.get('isDirty')) { return; }
    this.set('isLoading', true);
    let content = this.get('content');
    this.get('communities').updateCommunity(content).then(() => {
      if (this.isDestroyed) { return; }
      this.get('communities').getCommunityInfo(this.get('content.name')).then(data => {
        if (this.isDestroyed) { return; }
        // Fields to send to tracking
        ['description', 'summary', 'rules'].forEach(item => {
          this._trackUpdate(item);
        });

        this.set('editMode', false);
        this.set('isLoading', false);

        this.set('content', data);
        for (let key in content) {
          this.set(`rollbackData.${key}`, content[key]);
        }
      });
    });

    this.set('isDirty', false);
  },

  actions: {
    create() {
      this.create();
    },

    update() {
      this.update();
    }
  }
});
