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

  var ADMIN_LINKS = [
    {
      url: '/admin/groups',
      name: 'Groups',
    },
    {
      url: '/admin/create-group',
      name: 'Create Group',
      capability: 'createGroup'
    },
    {
      url: '/admin/projects',
      name: 'Projects',
    },
    {
      url: '/admin/create-project',
      name: 'Create Project',
      capability: 'createProject',
    },
    {
      url: '/admin/plugins',
      name: 'Plugins',
      capability: 'viewPlugins',
    },
  ];

  var DEFAULT_LINKS = [{
    title: 'Changes',
    links: [
      {
        url: '/q/status:open',
        name: 'Open',
      },
      {
        url: '/q/status:merged',
        name: 'Merged',
      },
      {
        url: '/q/status:abandoned',
        name: 'Abandoned',
      },
    ],
  }];

  var DOCUMENTATION_LINKS = [
    {
      url : '/index.html',
      name : 'Table of Contents',
    },
    {
      url : '/user-search.html',
      name : 'Searching',
    },
    {
      url : '/user-upload.html',
      name : 'Uploading',
    },
    {
      url : '/access-control.html',
      name : 'Access Control',
    },
    {
      url : '/rest-api.html',
      name : 'REST API',
    },
    {
      url : '/intro-project-owner.html',
      name : 'Project Owner Guide',
    }
  ];

  Polymer({
    is: 'gr-main-header',

    hostAttributes: {
      role: 'banner',
    },

    properties: {
      searchQuery: {
        type: String,
        notify: true,
      },

      _account: Object,
      _adminLinks: {
        type: Array,
        value: function() { return []; },
      },
      _defaultLinks: {
        type: Array,
        value: function() {
          return DEFAULT_LINKS;
        },
      },
      _docBaseUrl: {
        type: String,
      },
      _links: {
        type: Array,
        computed: '_computeLinks(_defaultLinks, _userLinks, _adminLinks, ' +
            '_docBaseUrl)',
      },
      _loginURL: {
        type: String,
        value: '/login',
      },
      _userLinks: {
        type: Array,
        value: function() { return []; },
      },
    },

    behaviors: [
      Gerrit.BaseUrlBehavior,
    ],

    observers: [
      '_accountLoaded(_account)',
    ],

    attached: function() {
      this._loadAccount();
      this._loadConfig();
      this.listen(window, 'location-change', '_handleLocationChange');
    },

    detached: function() {
      this.unlisten(window, 'location-change', '_handleLocationChange');
    },

    reload: function() {
      this._loadAccount();
    },

    _handleLocationChange: function(e) {
      if (this.getBaseUrl()) {
        // Strip the canonical path from the path since needing canonical in
        // the path is uneeded and breaks the url.
        this._loginURL = this.getBaseUrl() + '/login/' + encodeURIComponent(
            '/' + window.location.pathname.substring(this.getBaseUrl().length) +
            window.location.search +
            window.location.hash);
      } else {
        this._loginURL = '/login/' + encodeURIComponent(
            window.location.pathname +
            window.location.search +
            window.location.hash);
      }
    },

    _computeRelativeURL: function(path) {
      return '//' + window.location.host + this.getBaseUrl() + path;
    },

    _computeLinks: function(defaultLinks, userLinks, adminLinks, docBaseUrl) {
      var links = defaultLinks.slice();
      if (userLinks && userLinks.length > 0) {
        links.push({
          title: 'Your',
          links: userLinks,
        });
      }
      if (adminLinks && adminLinks.length > 0) {
        links.push({
          title: 'Admin',
          links: adminLinks,
        });
      }
      var docLinks = this._getDocLinks(docBaseUrl, DOCUMENTATION_LINKS);
      if (docLinks.length) {
        links.push({
          title: 'Documentation',
          links: docLinks,
        });
      }
      return links;
    },

    _getDocLinks: function(docBaseUrl, docLinks) {
      if (!docBaseUrl || !docLinks) {
        return [];
      }
      return docLinks.map(function(link) {
        var url = docBaseUrl;
        if (url && url[url.length - 1] === '/') {
          url = url.substring(0, url.length - 1);
        }
        return {
          url: url + link.url,
          name: link.name,
          target: '_blank',
        };
      });
    },

    _loadAccount: function() {
      this.$.restAPI.getAccount().then(function(account) {
        this._account = account;
        this.$.accountContainer.classList.toggle('loggedIn', account != null);
        this.$.accountContainer.classList.toggle('loggedOut', account == null);
      }.bind(this));
    },

    _loadConfig: function() {
      this.$.restAPI.getConfig().then(function(config) {
        if (config && config.gerrit && config.gerrit.doc_url) {
          this._docBaseUrl = config.gerrit.doc_url;
        }
        if (!this._docBaseUrl) {
          return this._probeDocLink('/Documentation/index.html');
        }
      }.bind(this));
    },

    _probeDocLink: function(path) {
      return this.$.restAPI.probePath(this.getBaseUrl() + path).then(function(ok) {
        if (ok) {
          this._docBaseUrl = this.getBaseUrl() + '/Documentation';
        } else {
          this._docBaseUrl = null;
        }
      }.bind(this));
    },

    _accountLoaded: function(account) {
      if (!account) { return; }

      this.$.restAPI.getPreferences().then(function(prefs) {
        this._userLinks =
            prefs.my.map(this._fixMyMenuItem).filter(this._isSupportedLink);
      }.bind(this));
      this._loadAccountCapabilities();
    },

    _loadAccountCapabilities: function() {
      var params = ['createProject', 'createGroup', 'viewPlugins'];
      return this.$.restAPI.getAccountCapabilities(params)
          .then(function(capabilities) {
        this._adminLinks = ADMIN_LINKS.filter(function(link) {
          return !link.capability ||
              capabilities.hasOwnProperty(link.capability);
        });
      }.bind(this));
    },

    _fixMyMenuItem: function(linkObj) {
      // Normalize all urls to PolyGerrit style.
      if (linkObj.url.indexOf('#') === 0) {
        linkObj.url = linkObj.url.slice(1);
      }

      // Delete target property due to complications of
      // https://bugs.chromium.org/p/gerrit/issues/detail?id=5888
      //
      // The server tries to guess whether URL is a view within the UI.
      // If not, it sets target='_blank' on the menu item. The server
      // makes assumptions that work for the GWT UI, but not PolyGerrit,
      // so we'll just disable it altogether for now.
      delete linkObj.target;

      // Becasue the "my menu" links may be arbitrary URLs, we don't know
      // whether they correspond to any client routes. Mark all such links as
      // external.
      linkObj.external = true;

      return linkObj;
    },

    _isSupportedLink: function(linkObj) {
      // Groups are not yet supported.
      return linkObj.url.indexOf('/groups') !== 0;
    },
  });
})();
