/**
 * @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.
 */
import '../../../scripts/bundled-polymer.js';

import '../../../behaviors/rest-client-behavior/rest-client-behavior.js';
import '../../../styles/shared-styles.js';
import '../../../styles/gr-change-metadata-shared-styles.js';
import '../../../styles/gr-change-view-integration-shared-styles.js';
import '../../../styles/gr-voting-styles.js';
import '../../core/gr-navigation/gr-navigation.js';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.js';
import '../../plugins/gr-endpoint-param/gr-endpoint-param.js';
import '../../plugins/gr-external-style/gr-external-style.js';
import '../../shared/gr-account-chip/gr-account-chip.js';
import '../../shared/gr-account-link/gr-account-link.js';
import '../../shared/gr-date-formatter/gr-date-formatter.js';
import '../../shared/gr-editable-label/gr-editable-label.js';
import '../../shared/gr-icons/gr-icons.js';
import '../../shared/gr-limited-text/gr-limited-text.js';
import '../../shared/gr-linked-chip/gr-linked-chip.js';
import '../../shared/gr-tooltip-content/gr-tooltip-content.js';
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import '../gr-change-requirements/gr-change-requirements.js';
import '../gr-commit-info/gr-commit-info.js';
import '../gr-reviewer-list/gr-reviewer-list.js';
import '../../shared/gr-account-list/gr-account-list.js';
import '../../../scripts/gr-display-name-utils/gr-display-name-utils.js';
import '../../../scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-change-metadata_html.js';

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
 * @extends Polymer.Element
 */
class GrChangeMetadata extends mixinBehaviors( [
  Gerrit.RESTClientBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get template() { return htmlTemplate; }

  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;
  }

  _showCherryPickOf(changeRecord) {
    const hasCherryPickOf = !!changeRecord &&
        !!changeRecord.base && !!changeRecord.base.cherry_pick_of_change &&
        !!changeRecord.base.cherry_pick_of_patch_set;
    return hasCherryPickOf;
  }

  _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');
  }

  _computeShowRepoBranchTogether(repo, branch) {
    return !!repo && !!branch && repo.length + branch.length < 40;
  }

  _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());
  }

  _computeCherryPickOfUrl(change, patchset, project) {
    return Gerrit.Nav.getUrlForChangeById(change, project, patchset);
  }

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

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

  _handleTopicRemoved(e) {
    const target = 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 = 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.shadowRoot.querySelector('.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);
