// 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';

  Polymer({
    is: 'gr-change-view',

    /**
     * Fired when the title of the page should change.
     *
     * @event title-change
     */

    properties: {
      /**
       * URL params passed from the router.
       */
      params: {
        type: Object,
        observer: '_paramsChanged',
      },
      viewState: {
        type: Object,
        notify: true,
        value: function() { return {}; },
      },
      serverConfig: Object,
      keyEventTarget: {
        type: Object,
        value: function() { return document.body; },
      },

      _comments: Object,
      _change: {
        type: Object,
        observer: '_changeChanged',
      },
      _commitInfo: Object,
      _changeNum: String,
      _diffDrafts: Object,
      _patchNum: String,
      _allPatchSets: {
        type: Array,
        computed: '_computeAllPatchSets(_change)',
      },
      _loggedIn: {
        type: Boolean,
        value: false,
      },
      _loading: Boolean,
      _headerContainerEl: Object,
      _headerEl: Object,
      _projectConfig: Object,
      _boundScrollHandler: {
        type: Function,
        value: function() { return this._handleBodyScroll.bind(this); },
      },
      _replyButtonLabel: {
        type: String,
        value: 'Reply',
        computed: '_computeReplyButtonLabel(_diffDrafts)',
      },
    },

    behaviors: [
      Gerrit.KeyboardShortcutBehavior,
      Gerrit.RESTClientBehavior,
    ],

    ready: function() {
      this._headerEl = this.$$('.header');
    },

    attached: function() {
      this._getLoggedIn().then(function(loggedIn) {
        this._loggedIn = loggedIn;
      }.bind(this));

      window.addEventListener('scroll', this._boundScrollHandler);
    },

    detached: function() {
      window.removeEventListener('scroll', this._boundScrollHandler);
    },

    _handleBodyScroll: function(e) {
      var containerEl = this._headerContainerEl ||
          this.$$('.headerContainer');

      // Calculate where the header is relative to the window.
      var top = containerEl.offsetTop;
      for (var offsetParent = containerEl.offsetParent;
           offsetParent;
           offsetParent = offsetParent.offsetParent) {
        top += offsetParent.offsetTop;
      }
      // The element may not be displayed yet, in which case do nothing.
      if (top == 0) { return; }

      this._headerEl.classList.toggle('pinned', window.scrollY >= top);
    },

    _resetHeaderEl: function() {
      var el = this._headerEl || this.$$('.header');
      this._headerEl = el;
      el.classList.remove('pinned');
    },

    _handlePatchChange: function(e) {
      var patchNum = e.target.value;
      var currentPatchNum =
          this._change.revisions[this._change.current_revision]._number;
      if (patchNum == currentPatchNum) {
        page.show(this.changePath(this._changeNum));
        return;
      }
      page.show(this.changePath(this._changeNum) + '/' + patchNum);
    },

    _handleReplyTap: function(e) {
      e.preventDefault();
      this.$.replyOverlay.open();
    },

    _handleDownloadTap: function(e) {
      e.preventDefault();
      this.$.downloadOverlay.open();
    },

    _handleDownloadDialogClose: function(e) {
      this.$.downloadOverlay.close();
    },

    _handleMessageReply: function(e) {
      var msg = e.detail.message.message;
      var quoteStr = msg.split('\n').map(
          function(line) { return '> ' + line; }).join('\n') + '\n\n';
      this.$.replyDialog.draft += quoteStr;
      this.$.replyOverlay.open();
    },

    _handleReplyOverlayOpen: function(e) {
      this.$.replyDialog.focus();
    },

    _handleReplySent: function(e) {
      this.$.replyOverlay.close();
      this._reload();
    },

    _handleReplyCancel: function(e) {
      this.$.replyOverlay.close();
    },

    _paramsChanged: function(value) {
      if (value.view != this.tagName.toLowerCase()) { return; }

      this._changeNum = value.changeNum;
      this._patchNum = value.patchNum;
      if (this.viewState.changeNum != this._changeNum ||
          this.viewState.patchNum != this._patchNum) {
        this.set('viewState.selectedFileIndex', 0);
        this.set('viewState.changeNum', this._changeNum);
        this.set('viewState.patchNum', this._patchNum);
      }
      if (!this._changeNum) {
        return;
      }
      this._reload().then(function() {
        this.$.messageList.topMargin = this._headerEl.offsetHeight;

        // Allow the message list to render before scrolling.
        this.async(function() {
          var msgPrefix = '#message-';
          var hash = window.location.hash;
          if (hash.indexOf(msgPrefix) == 0) {
            this.$.messageList.scrollToMessage(hash.substr(msgPrefix.length));
          }
        }.bind(this), 1);

        this._getLoggedIn().then(function(loggedIn) {
          if (!loggedIn) { return; }

          if (this.viewState.showReplyDialog) {
            this.$.replyOverlay.open();
            this.set('viewState.showReplyDialog', false);
          }
        }.bind(this));
      }.bind(this));
    },

    _changeChanged: function(change) {
      if (!change) { return; }
      this._patchNum = this._patchNum ||
          change.revisions[change.current_revision]._number;

      var title = change.subject + ' (' + change.change_id.substr(0, 9) + ')';
      this.fire('title-change', {title: title});
    },

    _computeChangePermalink: function(changeNum) {
      return '/' + changeNum;
    },

    _computeChangeStatus: function(change, patchNum) {
      var status = change.status;
      if (status == this.ChangeStatus.NEW) {
        var rev = this._getRevisionNumber(change, patchNum);
        // TODO(davido): Figure out, why sometimes revision is not there
        if (rev == undefined || !rev.draft) { return ''; }
        status = this.ChangeStatus.DRAFT;
      }
      return '(' + status.toLowerCase() + ')';
    },

    _computeDetailPath: function(changeNum) {
      return '/changes/' + changeNum + '/detail';
    },

    _computeCommitInfoPath: function(changeNum, patchNum) {
      return this.changeBaseURL(changeNum, patchNum) + '/commit?links';
    },

    _computeCommentsPath: function(changeNum) {
      return '/changes/' + changeNum + '/comments';
    },

    _computeProjectConfigPath: function(project) {
      return '/projects/' + encodeURIComponent(project) + '/config';
    },

    _computeDetailQueryParams: function() {
      var options = this.listChangesOptionsToHex(
          this.ListChangesOption.ALL_REVISIONS,
          this.ListChangesOption.CHANGE_ACTIONS,
          this.ListChangesOption.DOWNLOAD_COMMANDS
      );
      return {O: options};
    },

    _computeLatestPatchNum: function(change) {
      return change.revisions[change.current_revision]._number;
    },

    _computeAllPatchSets: function(change) {
      var patchNums = [];
      for (var rev in change.revisions) {
        patchNums.push(change.revisions[rev]._number);
      }
      return patchNums.sort(function(a, b) {
        return a - b;
      });
    },

    _getRevisionNumber: function(change, patchNum) {
      for (var rev in change.revisions) {
        if (change.revisions[rev]._number == patchNum) {
          return change.revisions[rev];
        }
      }
    },

    _computePatchIndexIsSelected: function(index, patchNum) {
      return this._allPatchSets[index] == patchNum;
    },

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

    _computeLabelValues: function(labelName, labels) {
      var result = [];
      var t = labels[labelName];
      if (!t) { return result; }
      var approvals = t.all || [];
      approvals.forEach(function(label) {
        if (label.value && label.value != labels[labelName].default_value) {
          var labelClassName;
          var labelValPrefix = '';
          if (label.value > 0) {
            labelValPrefix = '+';
            labelClassName = 'approved';
          } else if (label.value < 0) {
            labelClassName = 'notApproved';
          }
          result.push({
            value: labelValPrefix + label.value,
            className: labelClassName,
            account: label,
          });
        }
      });
      return result;
    },

    _computeReplyButtonHighlighted: function(drafts) {
      return Object.keys(drafts || {}).length > 0;
    },

    _computeReplyButtonLabel: function(drafts) {
      drafts = drafts || {};
      var draftCount = Object.keys(drafts).reduce(function(count, file) {
        return count + drafts[file].length;
      }, 0);

      var label = 'Reply';
      if (draftCount > 0) {
        label += ' (' + draftCount + ')';
      }
      return label;
    },

    _handleKey: function(e) {
      if (this.shouldSupressKeyboardShortcut(e)) { return; }

      switch (e.keyCode) {
        case 65:  // 'a'
          if (!this._loggedIn) { return; }

          e.preventDefault();
          this.$.replyOverlay.open();
          break;
        case 85:  // 'u'
          e.preventDefault();
          page.show('/');
          break;
      }
    },

    _handleReloadChange: function() {
      page.show(this.changePath(this._changeNum));
    },

    _getDiffDrafts: function() {
      return this.$.restAPI.getDiffDrafts(this._changeNum).then(
          function(drafts) { return this._diffDrafts = drafts; }.bind(this));
    },

    _getLoggedIn: function() {
      return this.$.restAPI.getLoggedIn();
    },

    _reloadDiffDrafts: function() {
      this._diffDrafts = {};
      this._getDiffDrafts().then(function() {
        if (this.$.replyOverlay.opened) {
          this.async(function() { this.$.replyOverlay.center(); }, 1);
        }
      }.bind(this));
    },

    _reload: function() {
      this._getLoggedIn().then(function(loggedIn) {
        if (!loggedIn) { return; }

        this._reloadDiffDrafts();
      }.bind(this));

      var detailCompletes = this.$.detailXHR.generateRequest().completes;
      this.$.commentsXHR.generateRequest();

      var reloadPatchNumDependentResources = function() {
        return Promise.all([
          this.$.commitInfoXHR.generateRequest().completes,
          this.$.actions.reload(),
          this.$.fileList.reload(),
        ]);
      }.bind(this);
      var reloadDetailDependentResources = function() {
        return this.$.relatedChanges.reload();
      }.bind(this);

      this._resetHeaderEl();

      if (this._patchNum) {
        return reloadPatchNumDependentResources().then(function() {
          return detailCompletes;
        }).then(reloadDetailDependentResources);
      } else {
        // The patch number is reliant on the change detail request.
        return detailCompletes.then(reloadPatchNumDependentResources).then(
            reloadDetailDependentResources);
      }
    },
  });
})();
