/**
 * @license
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
(function() {
  'use strict';

  const HASHTAG_ADD_MESSAGE = 'Add Hashtag';

  const SubmitTypeLabel = {
    FAST_FORWARD_ONLY: 'Fast Forward Only',
    MERGE_IF_NECESSARY: 'Merge if Necessary',
    REBASE_IF_NECESSARY: 'Rebase if Necessary',
    MERGE_ALWAYS: 'Always Merge',
    REBASE_ALWAYS: 'Rebase Always',
    CHERRY_PICK: 'Cherry Pick',
  };

  const NOT_CURRENT_MESSAGE = 'Not current - rebase possible';

  /**
   * @enum {string}
   */
  const CertificateStatus = {
    /**
     * This certificate status is bad.
     */
    BAD: 'BAD',
    /**
     * This certificate status is OK.
     */
    OK: 'OK',
    /**
     * This certificate status is TRUSTED.
     */
    TRUSTED: 'TRUSTED',
  };

  /**
    * @appliesMixin Gerrit.RESTClientMixin
    */
  class GrChangeMetadata extends Polymer.mixinBehaviors( [
    Gerrit.RESTClientBehavior,
  ], Polymer.GestureEventListeners(
      Polymer.LegacyElementMixin(
          Polymer.Element))) {
    static get is() { return 'gr-change-metadata'; }
    /**
     * Fired when the change topic is changed.
     *
     * @event topic-changed
     */

    static get properties() {
      return {
      /** @type {?} */
        change: Object,
        labels: {
          type: Object,
          notify: true,
        },
        account: Object,
        /** @type {?} */
        revision: Object,
        commitInfo: Object,
        _mutable: {
          type: Boolean,
          computed: '_computeIsMutable(account)',
        },
        /** @type {?} */
        serverConfig: Object,
        parentIsCurrent: Boolean,
        _notCurrentMessage: {
          type: String,
          value: NOT_CURRENT_MESSAGE,
          readOnly: true,
        },
        _topicReadOnly: {
          type: Boolean,
          computed: '_computeTopicReadOnly(_mutable, change)',
        },
        _hashtagReadOnly: {
          type: Boolean,
          computed: '_computeHashtagReadOnly(_mutable, change)',
        },
        /**
       * @type {Gerrit.PushCertificateValidation}
       */
        _pushCertificateValidation: {
          type: Object,
          computed: '_computePushCertificateValidation(serverConfig, change)',
        },
        _showRequirements: {
          type: Boolean,
          computed: '_computeShowRequirements(change)',
        },

        _assignee: Array,
        _isWip: {
          type: Boolean,
          computed: '_computeIsWip(change)',
        },
        _newHashtag: String,

        _settingTopic: {
          type: Boolean,
          value: false,
        },

        _currentParents: {
          type: Array,
          computed: '_computeParents(change)',
        },

        /** @type {?} */
        _CHANGE_ROLE: {
          type: Object,
          readOnly: true,
          value: {
            OWNER: 'owner',
            UPLOADER: 'uploader',
            AUTHOR: 'author',
            COMMITTER: 'committer',
          },
        },
      };
    }

    static get observers() {
      return [
        '_changeChanged(change)',
        '_labelsChanged(change.labels)',
        '_assigneeChanged(_assignee.*)',
      ];
    }

    _labelsChanged(labels) {
      this.labels = Object.assign({}, labels) || null;
    }

    _changeChanged(change) {
      this._assignee = change.assignee ? [change.assignee] : [];
    }

    _assigneeChanged(assigneeRecord) {
      if (!this.change) { return; }
      const assignee = assigneeRecord.base;
      if (assignee.length) {
        const acct = assignee[0];
        if (this.change.assignee &&
            acct._account_id === this.change.assignee._account_id) { return; }
        this.set(['change', 'assignee'], acct);
        this.$.restAPI.setAssignee(this.change._number, acct._account_id);
      } else {
        if (!this.change.assignee) { return; }
        this.set(['change', 'assignee'], undefined);
        this.$.restAPI.deleteAssignee(this.change._number);
      }
    }

    _computeHideStrategy(change) {
      return !this.changeIsOpen(change);
    }

    /**
     * @param {Object} commitInfo
     * @return {?Array} If array is empty, returns null instead so
     * an existential check can be used to hide or show the webLinks
     * section.
     */
    _computeWebLinks(commitInfo, serverConfig) {
      if (!commitInfo) { return null; }
      const weblinks = Gerrit.Nav.getChangeWeblinks(
          this.change ? this.change.repo : '',
          commitInfo.commit,
          {
            weblinks: commitInfo.web_links,
            config: serverConfig,
          });
      return weblinks.length ? weblinks : null;
    }

    _computeStrategy(change) {
      return SubmitTypeLabel[change.submit_type];
    }

    _computeLabelNames(labels) {
      return Object.keys(labels).sort();
    }

    _handleTopicChanged(e, topic) {
      const lastTopic = this.change.topic;
      if (!topic.length) { topic = null; }
      this._settingTopic = true;
      this.$.restAPI.setChangeTopic(this.change._number, topic)
          .then(newTopic => {
            this._settingTopic = false;
            this.set(['change', 'topic'], newTopic);
            if (newTopic !== lastTopic) {
              this.dispatchEvent(new CustomEvent(
                  'topic-changed', {bubbles: true, composed: true}));
            }
          });
    }

    _showAddTopic(changeRecord, settingTopic) {
      const hasTopic = !!changeRecord &&
          !!changeRecord.base && !!changeRecord.base.topic;
      return !hasTopic && !settingTopic;
    }

    _showTopicChip(changeRecord, settingTopic) {
      const hasTopic = !!changeRecord &&
          !!changeRecord.base && !!changeRecord.base.topic;
      return hasTopic && !settingTopic;
    }

    _handleHashtagChanged(e) {
      const lastHashtag = this.change.hashtag;
      if (!this._newHashtag.length) { return; }
      const newHashtag = this._newHashtag;
      this._newHashtag = '';
      this.$.restAPI.setChangeHashtag(
          this.change._number, {add: [newHashtag]}).then(newHashtag => {
        this.set(['change', 'hashtags'], newHashtag);
        if (newHashtag !== lastHashtag) {
          this.dispatchEvent(new CustomEvent(
              'hashtag-changed', {bubbles: true, composed: true}));
        }
      });
    }

    _computeTopicReadOnly(mutable, change) {
      return !mutable ||
          !change ||
          !change.actions ||
          !change.actions.topic ||
          !change.actions.topic.enabled;
    }

    _computeHashtagReadOnly(mutable, change) {
      return !mutable ||
          !change ||
          !change.actions ||
          !change.actions.hashtags ||
          !change.actions.hashtags.enabled;
    }

    _computeAssigneeReadOnly(mutable, change) {
      return !mutable ||
          !change ||
          !change.actions ||
          !change.actions.assignee ||
          !change.actions.assignee.enabled;
    }

    _computeTopicPlaceholder(_topicReadOnly) {
      // Action items in Material Design are uppercase -- placeholder label text
      // is sentence case.
      return _topicReadOnly ? 'No topic' : 'ADD TOPIC';
    }

    _computeHashtagPlaceholder(_hashtagReadOnly) {
      return _hashtagReadOnly ? '' : HASHTAG_ADD_MESSAGE;
    }

    _computeShowRequirements(change) {
      if (change.status !== this.ChangeStatus.NEW) {
        // TODO(maximeg) change this to display the stored
        // requirements, once it is implemented server-side.
        return false;
      }
      const hasRequirements = !!change.requirements &&
          Object.keys(change.requirements).length > 0;
      const hasLabels = !!change.labels &&
          Object.keys(change.labels).length > 0;
      return hasRequirements || hasLabels || !!change.work_in_progress;
    }

    /**
     * @return {?Gerrit.PushCertificateValidation} object representing data for
     *     the push validation.
     */
    _computePushCertificateValidation(serverConfig, change) {
      if (!change || !serverConfig || !serverConfig.receive ||
          !serverConfig.receive.enable_signed_push) {
        return null;
      }
      const rev = change.revisions[change.current_revision];
      if (!rev.push_certificate || !rev.push_certificate.key) {
        return {
          class: 'help',
          icon: 'gr-icons:help',
          message: 'This patch set was created without a push certificate',
        };
      }

      const key = rev.push_certificate.key;
      switch (key.status) {
        case CertificateStatus.BAD:
          return {
            class: 'invalid',
            icon: 'gr-icons:close',
            message: this._problems('Push certificate is invalid', key),
          };
        case CertificateStatus.OK:
          return {
            class: 'notTrusted',
            icon: 'gr-icons:info',
            message: this._problems(
                'Push certificate is valid, but key is not trusted', key),
          };
        case CertificateStatus.TRUSTED:
          return {
            class: 'trusted',
            icon: 'gr-icons:check',
            message: this._problems(
                'Push certificate is valid and key is trusted', key),
          };
        default:
          throw new Error(`unknown certificate status: ${key.status}`);
      }
    }

    _problems(msg, key) {
      if (!key || !key.problems || key.problems.length === 0) {
        return msg;
      }

      return [msg + ':'].concat(key.problems).join('\n');
    }

    _computeProjectURL(project) {
      return Gerrit.Nav.getUrlForProjectChanges(project);
    }

    _computeBranchURL(project, branch) {
      if (!this.change || !this.change.status) return '';
      return Gerrit.Nav.getUrlForBranch(branch, project,
          this.change.status == this.ChangeStatus.NEW ? 'open' :
            this.change.status.toLowerCase());
    }

    _computeTopicURL(topic) {
      return Gerrit.Nav.getUrlForTopic(topic);
    }

    _computeHashtagURL(hashtag) {
      return Gerrit.Nav.getUrlForHashtag(hashtag);
    }

    _handleTopicRemoved(e) {
      const target = Polymer.dom(e).rootTarget;
      target.disabled = true;
      this.$.restAPI.setChangeTopic(this.change._number, null).then(() => {
        target.disabled = false;
        this.set(['change', 'topic'], '');
        this.dispatchEvent(
            new CustomEvent('topic-changed', {bubbles: true, composed: true}));
      }).catch(err => {
        target.disabled = false;
        return;
      });
    }

    _handleHashtagRemoved(e) {
      e.preventDefault();
      const target = Polymer.dom(e).rootTarget;
      target.disabled = true;
      this.$.restAPI.setChangeHashtag(this.change._number,
          {remove: [target.text]})
          .then(newHashtag => {
            target.disabled = false;
            this.set(['change', 'hashtags'], newHashtag);
          }).catch(err => {
            target.disabled = false;
            return;
          });
    }

    _computeIsWip(change) {
      return !!change.work_in_progress;
    }

    _computeShowRoleClass(change, role) {
      return this._getNonOwnerRole(change, role) ? '' : 'hideDisplay';
    }

    /**
     * Get the user with the specified role on the change. Returns null if the
     * user with that role is the same as the owner.
     * @param {!Object} change
     * @param {string} role One of the values from _CHANGE_ROLE
     * @return {Object|null} either an accound or null.
     */
    _getNonOwnerRole(change, role) {
      if (!change || !change.current_revision ||
          !change.revisions[change.current_revision]) {
        return null;
      }

      const rev = change.revisions[change.current_revision];
      if (!rev) { return null; }

      if (role === this._CHANGE_ROLE.UPLOADER &&
          rev.uploader &&
          change.owner._account_id !== rev.uploader._account_id) {
        return rev.uploader;
      }

      if (role === this._CHANGE_ROLE.AUTHOR &&
          rev.commit && rev.commit.author &&
          change.owner.email !== rev.commit.author.email) {
        return rev.commit.author;
      }

      if (role === this._CHANGE_ROLE.COMMITTER &&
          rev.commit && rev.commit.committer &&
          change.owner.email !== rev.commit.committer.email) {
        return rev.commit.committer;
      }

      return null;
    }

    _computeParents(change) {
      if (!change || !change.current_revision ||
          !change.revisions[change.current_revision] ||
          !change.revisions[change.current_revision].commit) {
        return undefined;
      }
      return change.revisions[change.current_revision].commit.parents;
    }

    _computeParentsLabel(parents) {
      return parents && parents.length > 1 ? 'Parents' : 'Parent';
    }

    _computeParentListClass(parents, parentIsCurrent) {
      // Undefined check for polymer 2
      if (parents === undefined || parentIsCurrent === undefined) {
        return '';
      }

      return [
        'parentList',
        parents && parents.length > 1 ? 'merge' : 'nonMerge',
        parentIsCurrent ? 'current' : 'notCurrent',
      ].join(' ');
    }

    _computeIsMutable(account) {
      return !!Object.keys(account).length;
    }

    editTopic() {
      if (this._topicReadOnly || this.change.topic) { return; }
      // Cannot use `this.$.ID` syntax because the element exists inside of a
      // dom-if.
      this.$$('.topicEditableLabel').open();
    }

    _getReviewerSuggestionsProvider(change) {
      const provider = GrReviewerSuggestionsProvider.create(this.$.restAPI,
          change._number, Gerrit.SUGGESTIONS_PROVIDERS_USERS_TYPES.ANY);
      provider.init();
      return provider;
    }
  }

  customElements.define(GrChangeMetadata.is, GrChangeMetadata);
})();
