/**
 * @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 RoutePattern = {
    ROOT: '/',

    DASHBOARD: /^\/dashboard\/(.+)$/,
    CUSTOM_DASHBOARD: /^\/dashboard\/?$/,
    PROJECT_DASHBOARD: /^\/p\/(.+)\/\+\/dashboard\/(.+)/,

    AGREEMENTS: /^\/settings\/agreements\/?/,
    NEW_AGREEMENTS: /^\/settings\/new-agreement\/?/,
    REGISTER: /^\/register(\/.*)?$/,

    // Pattern for login and logout URLs intended to be passed-through. May
    // include a return URL.
    LOG_IN_OR_OUT: /\/log(in|out)(\/(.+))?$/,

    // Pattern for a catchall route when no other pattern is matched.
    DEFAULT: /.*/,

    // Matches /admin/groups/[uuid-]<group>
    GROUP: /^\/admin\/groups\/(?:uuid-)?([^,]+)$/,

    // Redirects /groups/self to /settings/#Groups for GWT compatibility
    GROUP_SELF: /^\/groups\/self/,

    // Matches /admin/groups/[uuid-]<group>,info (backwords compat with gwtui)
    // Redirects to /admin/groups/[uuid-]<group>
    GROUP_INFO: /^\/admin\/groups\/(?:uuid-)?(.+),info$/,

    // Matches /admin/groups/<group>,audit-log
    GROUP_AUDIT_LOG: /^\/admin\/groups\/(?:uuid-)?(.+),audit-log$/,

    // Matches /admin/groups/[uuid-]<group>,members
    GROUP_MEMBERS: /^\/admin\/groups\/(?:uuid-)?(.+),members$/,

    // Matches /admin/groups[,<offset>][/].
    GROUP_LIST_OFFSET: /^\/admin\/groups(,(\d+))?(\/)?$/,
    GROUP_LIST_FILTER: '/admin/groups/q/filter::filter',
    GROUP_LIST_FILTER_OFFSET: '/admin/groups/q/filter::filter,:offset',

    // Matches /admin/create-project
    LEGACY_CREATE_PROJECT: /^\/admin\/create-project\/?$/,

    // Matches /admin/create-project
    LEGACY_CREATE_GROUP: /^\/admin\/create-group\/?$/,

    PROJECT_OLD: /^\/admin\/(projects)\/?(.+)?$/,

    // Matches /admin/repos/<repo>
    REPO: /^\/admin\/repos\/([^,]+)$/,

    // Matches /admin/repos/<repo>,commands.
    REPO_COMMANDS: /^\/admin\/repos\/(.+),commands$/,

    // Matches /admin/repos/<repos>,access.
    REPO_ACCESS: /^\/admin\/repos\/(.+),access$/,

    // Matches /admin/repos/<repos>,access.
    REPO_DASHBOARDS: /^\/admin\/repos\/(.+),dashboards$/,

    // Matches /admin/repos[,<offset>][/].
    REPO_LIST_OFFSET: /^\/admin\/repos(,(\d+))?(\/)?$/,
    REPO_LIST_FILTER: '/admin/repos/q/filter::filter',
    REPO_LIST_FILTER_OFFSET: '/admin/repos/q/filter::filter,:offset',

    // Matches /admin/repos/<repo>,branches[,<offset>].
    BRANCH_LIST_OFFSET: /^\/admin\/repos\/(.+),branches(,(.+))?$/,
    BRANCH_LIST_FILTER: '/admin/repos/:repo,branches/q/filter::filter',
    BRANCH_LIST_FILTER_OFFSET:
        '/admin/repos/:repo,branches/q/filter::filter,:offset',

    // Matches /admin/repos/<repo>,tags[,<offset>].
    TAG_LIST_OFFSET: /^\/admin\/repos\/(.+),tags(,(.+))?$/,
    TAG_LIST_FILTER: '/admin/repos/:repo,tags/q/filter::filter',
    TAG_LIST_FILTER_OFFSET:
        '/admin/repos/:repo,tags/q/filter::filter,:offset',

    PLUGINS: /^\/plugins\/(.+)$/,

    PLUGIN_LIST: /^\/admin\/plugins(\/)?$/,

    // Matches /admin/plugins[,<offset>][/].
    PLUGIN_LIST_OFFSET: /^\/admin\/plugins(,(\d+))?(\/)?$/,
    PLUGIN_LIST_FILTER: '/admin/plugins/q/filter::filter',
    PLUGIN_LIST_FILTER_OFFSET: '/admin/plugins/q/filter::filter,:offset',

    QUERY: /^\/q\/([^,]+)(,(\d+))?$/,

    /**
     * Support vestigial params from GWT UI.
     * @see Issue 7673.
     * @type {!RegExp}
     */
    QUERY_LEGACY_SUFFIX: /^\/q\/.+,n,z$/,

    // Matches /c/<changeNum>/[<basePatchNum>..][<patchNum>][/].
    CHANGE_LEGACY: /^\/c\/(\d+)\/?(((-?\d+|edit)(\.\.(\d+|edit))?))?\/?$/,
    CHANGE_NUMBER_LEGACY: /^\/(\d+)\/?/,

    // Matches
    // /c/<project>/+/<changeNum>/[<basePatchNum|edit>..][<patchNum|edit>].
    // TODO(kaspern): Migrate completely to project based URLs, with backwards
    // compatibility for change-only.
    CHANGE: /^\/c\/(.+)\/\+\/(\d+)(\/?((-?\d+|edit)(\.\.(\d+|edit))?))?\/?$/,

    // Matches /c/<project>/+/<changeNum>/[<patchNum|edit>],edit
    CHANGE_EDIT: /^\/c\/(.+)\/\+\/(\d+)(\/(\d+))?,edit\/?$/,

    // Matches
    // /c/<project>/+/<changeNum>/[<basePatchNum|edit>..]<patchNum|edit>/<path>.
    // TODO(kaspern): Migrate completely to project based URLs, with backwards
    // compatibility for change-only.
    // eslint-disable-next-line max-len
    DIFF: /^\/c\/(.+)\/\+\/(\d+)(\/((-?\d+|edit)(\.\.(\d+|edit))?(\/(.+))))\/?$/,

    // Matches /c/<project>/+/<changeNum>/[<patchNum|edit>]/<path>,edit
    DIFF_EDIT: /^\/c\/(.+)\/\+\/(\d+)\/(\d+|edit)\/(.+),edit$/,

    // Matches non-project-relative
    // /c/<changeNum>/[<basePatchNum>..]<patchNum>/<path>.
    DIFF_LEGACY: /^\/c\/(\d+)\/((-?\d+|edit)(\.\.(\d+|edit))?)\/(.+)/,

    // Matches diff routes using @\d+ to specify a file name (whether or not
    // the project name is included).
    // eslint-disable-next-line max-len
    DIFF_LEGACY_LINENUM: /^\/c\/((.+)\/\+\/)?(\d+)(\/?((-?\d+|edit)(\.\.(\d+|edit))?\/(.+))?)@[ab]?\d+$/,

    SETTINGS: /^\/settings\/?/,
    SETTINGS_LEGACY: /^\/settings\/VE\/(\S+)/,

    // Matches /c/<changeNum>/ /<URL tail>
    // Catches improperly encoded URLs (context: Issue 7100)
    IMPROPERLY_ENCODED_PLUS: /^\/c\/(.+)\/\ \/(.+)$/,

    PLUGIN_SCREEN: /^\/x\/([\w-]+)\/([\w-]+)\/?/,

    DOCUMENTATION_SEARCH_FILTER: '/Documentation/q/filter::filter',
    DOCUMENTATION_SEARCH: /^\/Documentation\/q\/(.*)$/,
    DOCUMENTATION: /^\/Documentation(\/)?(.+)?/,
  };

  /**
   * Pattern to recognize and parse the diff line locations as they appear in
   * the hash of diff URLs. In this format, a number on its own indicates that
   * line number in the revision of the diff. A number prefixed by either an 'a'
   * or a 'b' indicates that line number of the base of the diff.
   * @type {RegExp}
   */
  const LINE_ADDRESS_PATTERN = /^([ab]?)(\d+)$/;

  /**
   * Pattern to recognize '+' in url-encoded strings for replacement with ' '.
   */
  const PLUS_PATTERN = /\+/g;

  /**
   * Pattern to recognize leading '?' in window.location.search, for stripping.
   */
  const QUESTION_PATTERN = /^\?*/;

  /**
   * GWT UI would use @\d+ at the end of a path to indicate linenum.
   */
  const LEGACY_LINENUM_PATTERN = /@([ab]?\d+)$/;

  const LEGACY_QUERY_SUFFIX_PATTERN = /,n,z$/;

  const REPO_TOKEN_PATTERN = /\$\{(project|repo)\}/g;

  // Polymer makes `app` intrinsically defined on the window by virtue of the
  // custom element having the id "app", but it is made explicit here.
  const app = document.querySelector('#app');
  if (!app) {
    console.log('No gr-app found (running tests)');
  }

  // Setup listeners outside of the router component initialization.
  (function() {
    const reporting = document.createElement('gr-reporting');

    window.addEventListener('load', () => {
      setTimeout(() => {
        reporting.pageLoaded();
      }, 0);
    });

    window.addEventListener('WebComponentsReady', () => {
      reporting.timeEnd('WebComponentsReady');
    });
  })();

  Polymer({
    is: 'gr-router',

    properties: {
      _app: {
        type: Object,
        value: app,
      },
      _isRedirecting: Boolean,
      // This variable is to differentiate between internal navigation (false)
      // and for first navigation in app after loaded from server (true).
      _isInitialLoad: {
        type: Boolean,
        value: true,
      },
    },

    behaviors: [
      Gerrit.BaseUrlBehavior,
      Gerrit.FireBehavior,
      Gerrit.PatchSetBehavior,
      Gerrit.URLEncodingBehavior,
    ],

    start() {
      if (!this._app) { return; }
      this._startRouter();
    },

    _setParams(params) {
      this._appElement().params = params;
    },

    _appElement() {
      // In Polymer2 you have to reach through the shadow root of the app
      // element. This obviously breaks encapsulation.
      // TODO(brohlfs): Make this more elegant, e.g. by exposing app-element
      // explicitly in app, or by delegating to it.
      return document.getElementById('app-element') ||
          document.getElementById('app').shadowRoot.getElementById(
              'app-element');
    },

    _redirect(url) {
      this._isRedirecting = true;
      page.redirect(url);
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateUrl(params) {
      const base = this.getBaseUrl();
      let url = '';
      const Views = Gerrit.Nav.View;

      if (params.view === Views.SEARCH) {
        url = this._generateSearchUrl(params);
      } else if (params.view === Views.CHANGE) {
        url = this._generateChangeUrl(params);
      } else if (params.view === Views.DASHBOARD) {
        url = this._generateDashboardUrl(params);
      } else if (params.view === Views.DIFF || params.view === Views.EDIT) {
        url = this._generateDiffOrEditUrl(params);
      } else if (params.view === Views.GROUP) {
        url = this._generateGroupUrl(params);
      } else if (params.view === Views.REPO) {
        url = this._generateRepoUrl(params);
      } else if (params.view === Views.ROOT) {
        url = '/';
      } else if (params.view === Views.SETTINGS) {
        url = this._generateSettingsUrl(params);
      } else {
        throw new Error('Can\'t generate');
      }

      return base + url;
    },

    _generateWeblinks(params) {
      const type = params.type;
      switch (type) {
        case Gerrit.Nav.WeblinkType.FILE:
          return this._getFileWebLinks(params);
        case Gerrit.Nav.WeblinkType.CHANGE:
          return this._getChangeWeblinks(params);
        case Gerrit.Nav.WeblinkType.PATCHSET:
          return this._getPatchSetWeblink(params);
        default:
          console.warn(`Unsupported weblink ${type}!`);
      }
    },

    _getPatchSetWeblink(params) {
      const {commit, options} = params;
      const {weblinks, config} = options || {};
      const name = commit && commit.slice(0, 7);
      const weblink = this._getBrowseCommitWeblink(weblinks, config);
      if (!weblink || !weblink.url) {
        return {name};
      } else {
        return {name, url: weblink.url};
      }
    },

    _firstCodeBrowserWeblink(weblinks) {
      // This is an ordered whitelist of web link types that provide direct
      // links to the commit in the url property.
      const codeBrowserLinks = ['gitiles', 'browse', 'gitweb'];
      for (let i = 0; i < codeBrowserLinks.length; i++) {
        const weblink =
          weblinks.find(weblink => weblink.name === codeBrowserLinks[i]);
        if (weblink) { return weblink; }
      }
      return null;
    },


    _getBrowseCommitWeblink(weblinks, config) {
      if (!weblinks) { return null; }
      let weblink;
      // Use primary weblink if configured and exists.
      if (config && config.gerrit && config.gerrit.primary_weblink_name) {
        weblink = weblinks.find(
            weblink => weblink.name === config.gerrit.primary_weblink_name
        );
      }
      if (!weblink) {
        weblink = this._firstCodeBrowserWeblink(weblinks);
      }
      if (!weblink) { return null; }
      return weblink;
    },

    _getChangeWeblinks({repo, commit, options: {weblinks, config}}) {
      if (!weblinks || !weblinks.length) return [];
      const commitWeblink = this._getBrowseCommitWeblink(weblinks, config);
      return weblinks.filter(weblink =>
        !commitWeblink ||
        !commitWeblink.name ||
        weblink.name !== commitWeblink.name);
    },

    _getFileWebLinks({repo, commit, file, options: {weblinks}}) {
      return weblinks;
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateSearchUrl(params) {
      let offsetExpr = '';
      if (params.offset && params.offset > 0) {
        offsetExpr = ',' + params.offset;
      }

      if (params.query) {
        return '/q/' + this.encodeURL(params.query, true) + offsetExpr;
      }

      const operators = [];
      if (params.owner) {
        operators.push('owner:' + this.encodeURL(params.owner, false));
      }
      if (params.project) {
        operators.push('project:' + this.encodeURL(params.project, false));
      }
      if (params.branch) {
        operators.push('branch:' + this.encodeURL(params.branch, false));
      }
      if (params.topic) {
        operators.push('topic:"' + this.encodeURL(params.topic, false) + '"');
      }
      if (params.hashtag) {
        operators.push('hashtag:"' +
            this.encodeURL(params.hashtag.toLowerCase(), false) + '"');
      }
      if (params.statuses) {
        if (params.statuses.length === 1) {
          operators.push(
              'status:' + this.encodeURL(params.statuses[0], false));
        } else if (params.statuses.length > 1) {
          operators.push(
              '(' +
              params.statuses.map(s => `status:${this.encodeURL(s, false)}`)
                  .join(' OR ') +
              ')');
        }
      }

      return '/q/' + operators.join('+') + offsetExpr;
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateChangeUrl(params) {
      let range = this._getPatchRangeExpression(params);
      if (range.length) { range = '/' + range; }
      let suffix = `${range}`;
      if (params.querystring) {
        suffix += '?' + params.querystring;
      } else if (params.edit) {
        suffix += ',edit';
      }
      if (params.messageHash) {
        suffix += params.messageHash;
      }
      if (params.project) {
        const encodedProject = this.encodeURL(params.project, true);
        return `/c/${encodedProject}/+/${params.changeNum}${suffix}`;
      } else {
        return `/c/${params.changeNum}${suffix}`;
      }
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateDashboardUrl(params) {
      const repoName = params.repo || params.project || null;
      if (params.sections) {
        // Custom dashboard.
        const queryParams = this._sectionsToEncodedParams(params.sections,
            repoName);
        if (params.title) {
          queryParams.push('title=' + encodeURIComponent(params.title));
        }
        const user = params.user ? params.user : '';
        return `/dashboard/${user}?${queryParams.join('&')}`;
      } else if (repoName) {
        // Project dashboard.
        const encodedRepo = this.encodeURL(repoName, true);
        return `/p/${encodedRepo}/+/dashboard/${params.dashboard}`;
      } else {
        // User dashboard.
        return `/dashboard/${params.user || 'self'}`;
      }
    },

    /**
     * @param {!Array<!{name: string, query: string}>} sections
     * @param {string=} opt_repoName
     * @return {!Array<string>}
     */
    _sectionsToEncodedParams(sections, opt_repoName) {
      return sections.map(section => {
        // If there is a repo name provided, make sure to substitute it into the
        // ${repo} (or legacy ${project}) query tokens.
        const query = opt_repoName ?
            section.query.replace(REPO_TOKEN_PATTERN, opt_repoName) :
            section.query;
        return encodeURIComponent(section.name) + '=' +
            encodeURIComponent(query);
      });
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateDiffOrEditUrl(params) {
      let range = this._getPatchRangeExpression(params);
      if (range.length) { range = '/' + range; }

      let suffix = `${range}/${this.encodeURL(params.path, true)}`;

      if (params.view === Gerrit.Nav.View.EDIT) { suffix += ',edit'; }

      if (params.lineNum) {
        suffix += '#';
        if (params.leftSide) { suffix += 'b'; }
        suffix += params.lineNum;
      }

      if (params.project) {
        const encodedProject = this.encodeURL(params.project, true);
        return `/c/${encodedProject}/+/${params.changeNum}${suffix}`;
      } else {
        return `/c/${params.changeNum}${suffix}`;
      }
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateGroupUrl(params) {
      let url = `/admin/groups/${this.encodeURL(params.groupId + '', true)}`;
      if (params.detail === Gerrit.Nav.GroupDetailView.MEMBERS) {
        url += ',members';
      } else if (params.detail === Gerrit.Nav.GroupDetailView.LOG) {
        url += ',audit-log';
      }
      return url;
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateRepoUrl(params) {
      let url = `/admin/repos/${this.encodeURL(params.repoName + '', true)}`;
      if (params.detail === Gerrit.Nav.RepoDetailView.ACCESS) {
        url += ',access';
      } else if (params.detail === Gerrit.Nav.RepoDetailView.BRANCHES) {
        url += ',branches';
      } else if (params.detail === Gerrit.Nav.RepoDetailView.TAGS) {
        url += ',tags';
      } else if (params.detail === Gerrit.Nav.RepoDetailView.COMMANDS) {
        url += ',commands';
      } else if (params.detail === Gerrit.Nav.RepoDetailView.DASHBOARDS) {
        url += ',dashboards';
      }
      return url;
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateSettingsUrl(params) {
      return '/settings';
    },

    /**
     * Given an object of parameters, potentially including a `patchNum` or a
     * `basePatchNum` or both, return a string representation of that range. If
     * no range is indicated in the params, the empty string is returned.
     * @param {!Object} params
     * @return {string}
     */
    _getPatchRangeExpression(params) {
      let range = '';
      if (params.patchNum) { range = '' + params.patchNum; }
      if (params.basePatchNum) { range = params.basePatchNum + '..' + range; }
      return range;
    },

    /**
     * Given a set of params without a project, gets the project from the rest
     * API project lookup and then sets the app params.
     *
     * @param {?Object} params
     */
    _normalizeLegacyRouteParams(params) {
      if (!params.changeNum) { return Promise.resolve(); }

      return this.$.restAPI.getFromProjectLookup(params.changeNum)
          .then(project => {
            // Show a 404 and terminate if the lookup request failed. Attempting
            // to redirect after failing to get the project loops infinitely.
            if (!project) {
              this._show404();
              return;
            }

            params.project = project;
            this._normalizePatchRangeParams(params);
            this._redirect(this._generateUrl(params));
          });
    },

    /**
     * Normalizes the params object, and determines if the URL needs to be
     * modified to fit the proper schema.
     *
     * @param {*} params
     * @return {boolean} whether or not the URL needs to be upgraded.
     */
    _normalizePatchRangeParams(params) {
      const hasBasePatchNum = params.basePatchNum !== null &&
          params.basePatchNum !== undefined;
      const hasPatchNum = params.patchNum !== null &&
          params.patchNum !== undefined;
      let needsRedirect = false;

      // Diffing a patch against itself is invalid, so if the base and revision
      // patches are equal clear the base.
      if (hasBasePatchNum &&
          this.patchNumEquals(params.basePatchNum, params.patchNum)) {
        needsRedirect = true;
        params.basePatchNum = null;
      } else if (hasBasePatchNum && !hasPatchNum) {
        // Regexes set basePatchNum instead of patchNum when only one is
        // specified. Redirect is not needed in this case.
        params.patchNum = params.basePatchNum;
        params.basePatchNum = null;
      }
      return needsRedirect;
    },

    /**
     * Redirect the user to login using the given return-URL for redirection
     * after authentication success.
     * @param {string} returnUrl
     */
    _redirectToLogin(returnUrl) {
      const basePath = this.getBaseUrl() || '';
      page(
          '/login/' + encodeURIComponent(returnUrl.substring(basePath.length)));
    },

    /**
     * Hashes parsed by page.js exclude "inner" hashes, so a URL like "/a#b#c"
     * is parsed to have a hash of "b" rather than "b#c". Instead, this method
     * parses hashes correctly. Will return an empty string if there is no hash.
     * @param {!string} canonicalPath
     * @return {!string} Everything after the first '#' ("a#b#c" -> "b#c").
     */
    _getHashFromCanonicalPath(canonicalPath) {
      return canonicalPath.split('#').slice(1).join('#');
    },

    _parseLineAddress(hash) {
      const match = hash.match(LINE_ADDRESS_PATTERN);
      if (!match) { return null; }
      return {
        leftSide: !!match[1],
        lineNum: parseInt(match[2], 10),
      };
    },

    /**
     * Check to see if the user is logged in and return a promise that only
     * resolves if the user is logged in. If the user us not logged in, the
     * promise is rejected and the page is redirected to the login flow.
     * @param {!Object} data The parsed route data.
     * @return {!Promise<!Object>} A promise yielding the original route data
     *     (if it resolves).
     */
    _redirectIfNotLoggedIn(data) {
      return this.$.restAPI.getLoggedIn().then(loggedIn => {
        if (loggedIn) {
          return Promise.resolve();
        } else {
          this._redirectToLogin(data.canonicalPath);
          return Promise.reject(new Error());
        }
      });
    },

    /**  Page.js middleware that warms the REST API's logged-in cache line. */
    _loadUserMiddleware(ctx, next) {
      this.$.restAPI.getLoggedIn().then(() => { next(); });
    },

    /**
     * Map a route to a method on the router.
     *
     * @param {!string|!RegExp} pattern The page.js pattern for the route.
     * @param {!string} handlerName The method name for the handler. If the
     *     route is matched, the handler will be executed with `this` referring
     *     to the component. Its return value will be discarded so that it does
     *     not interfere with page.js.
     * @param  {?boolean=} opt_authRedirect If true, then auth is checked before
     *     executing the handler. If the user is not logged in, it will redirect
     *     to the login flow and the handler will not be executed. The login
     *     redirect specifies the matched URL to be used after successfull auth.
     */
    _mapRoute(pattern, handlerName, opt_authRedirect) {
      if (!this[handlerName]) {
        console.error('Attempted to map route to unknown method: ',
            handlerName);
        return;
      }
      page(pattern, this._loadUserMiddleware.bind(this), data => {
        this.$.reporting.locationChanged(handlerName);
        const promise = opt_authRedirect ?
          this._redirectIfNotLoggedIn(data) : Promise.resolve();
        promise.then(() => { this[handlerName](data); });
      });
    },

    _startRouter() {
      const base = this.getBaseUrl();
      if (base) {
        page.base(base);
      }

      Gerrit.Nav.setup(
          url => { page.show(url); },
          this._generateUrl.bind(this),
          params => this._generateWeblinks(params),
          x => x
      );

      page.exit('*', (ctx, next) => {
        if (!this._isRedirecting) {
          this.$.reporting.beforeLocationChanged();
        }
        this._isRedirecting = false;
        this._isInitialLoad = false;
        next();
      });

      // Middleware
      page((ctx, next) => {
        document.body.scrollTop = 0;

        if (ctx.hash.match(RoutePattern.PLUGIN_SCREEN)) {
          // Redirect all urls using hash #/x/plugin/screen to /x/plugin/screen
          // This is needed to allow plugins to add basic #/x/ screen links to
          // any location.
          this._redirect(ctx.hash);
          return;
        }

        // Fire asynchronously so that the URL is changed by the time the event
        // is processed.
        this.async(() => {
          this.fire('location-change', {
            hash: window.location.hash,
            pathname: window.location.pathname,
          });
        }, 1);
        next();
      });

      this._mapRoute(RoutePattern.ROOT, '_handleRootRoute');

      this._mapRoute(RoutePattern.DASHBOARD, '_handleDashboardRoute');

      this._mapRoute(RoutePattern.CUSTOM_DASHBOARD,
          '_handleCustomDashboardRoute');

      this._mapRoute(RoutePattern.PROJECT_DASHBOARD,
          '_handleProjectDashboardRoute');

      this._mapRoute(RoutePattern.GROUP_INFO, '_handleGroupInfoRoute', true);

      this._mapRoute(RoutePattern.GROUP_AUDIT_LOG, '_handleGroupAuditLogRoute',
          true);

      this._mapRoute(RoutePattern.GROUP_MEMBERS, '_handleGroupMembersRoute',
          true);

      this._mapRoute(RoutePattern.GROUP_LIST_OFFSET,
          '_handleGroupListOffsetRoute', true);

      this._mapRoute(RoutePattern.GROUP_LIST_FILTER_OFFSET,
          '_handleGroupListFilterOffsetRoute', true);

      this._mapRoute(RoutePattern.GROUP_LIST_FILTER,
          '_handleGroupListFilterRoute', true);

      this._mapRoute(RoutePattern.GROUP_SELF, '_handleGroupSelfRedirectRoute',
          true);

      this._mapRoute(RoutePattern.GROUP, '_handleGroupRoute', true);

      this._mapRoute(RoutePattern.PROJECT_OLD,
          '_handleProjectsOldRoute');

      this._mapRoute(RoutePattern.REPO_COMMANDS,
          '_handleRepoCommandsRoute', true);

      this._mapRoute(RoutePattern.REPO_ACCESS,
          '_handleRepoAccessRoute');

      this._mapRoute(RoutePattern.REPO_DASHBOARDS,
          '_handleRepoDashboardsRoute');

      this._mapRoute(RoutePattern.BRANCH_LIST_OFFSET,
          '_handleBranchListOffsetRoute');

      this._mapRoute(RoutePattern.BRANCH_LIST_FILTER_OFFSET,
          '_handleBranchListFilterOffsetRoute');

      this._mapRoute(RoutePattern.BRANCH_LIST_FILTER,
          '_handleBranchListFilterRoute');

      this._mapRoute(RoutePattern.TAG_LIST_OFFSET,
          '_handleTagListOffsetRoute');

      this._mapRoute(RoutePattern.TAG_LIST_FILTER_OFFSET,
          '_handleTagListFilterOffsetRoute');

      this._mapRoute(RoutePattern.TAG_LIST_FILTER,
          '_handleTagListFilterRoute');

      this._mapRoute(RoutePattern.LEGACY_CREATE_GROUP,
          '_handleCreateGroupRoute', true);

      this._mapRoute(RoutePattern.LEGACY_CREATE_PROJECT,
          '_handleCreateProjectRoute', true);

      this._mapRoute(RoutePattern.REPO_LIST_OFFSET,
          '_handleRepoListOffsetRoute');

      this._mapRoute(RoutePattern.REPO_LIST_FILTER_OFFSET,
          '_handleRepoListFilterOffsetRoute');

      this._mapRoute(RoutePattern.REPO_LIST_FILTER,
          '_handleRepoListFilterRoute');

      this._mapRoute(RoutePattern.REPO, '_handleRepoRoute');

      this._mapRoute(RoutePattern.PLUGINS, '_handlePassThroughRoute');

      this._mapRoute(RoutePattern.PLUGIN_LIST_OFFSET,
          '_handlePluginListOffsetRoute', true);

      this._mapRoute(RoutePattern.PLUGIN_LIST_FILTER_OFFSET,
          '_handlePluginListFilterOffsetRoute', true);

      this._mapRoute(RoutePattern.PLUGIN_LIST_FILTER,
          '_handlePluginListFilterRoute', true);

      this._mapRoute(RoutePattern.PLUGIN_LIST, '_handlePluginListRoute', true);

      this._mapRoute(RoutePattern.QUERY_LEGACY_SUFFIX,
          '_handleQueryLegacySuffixRoute');

      this._mapRoute(RoutePattern.QUERY, '_handleQueryRoute');

      this._mapRoute(RoutePattern.DIFF_LEGACY_LINENUM, '_handleLegacyLinenum');

      this._mapRoute(RoutePattern.CHANGE_NUMBER_LEGACY,
          '_handleChangeNumberLegacyRoute');

      this._mapRoute(RoutePattern.DIFF_EDIT, '_handleDiffEditRoute', true);

      this._mapRoute(RoutePattern.CHANGE_EDIT, '_handleChangeEditRoute', true);

      this._mapRoute(RoutePattern.DIFF, '_handleDiffRoute');

      this._mapRoute(RoutePattern.CHANGE, '_handleChangeRoute');

      this._mapRoute(RoutePattern.CHANGE_LEGACY, '_handleChangeLegacyRoute');

      this._mapRoute(RoutePattern.DIFF_LEGACY, '_handleDiffLegacyRoute');

      this._mapRoute(RoutePattern.AGREEMENTS, '_handleAgreementsRoute', true);

      this._mapRoute(RoutePattern.NEW_AGREEMENTS, '_handleNewAgreementsRoute',
          true);

      this._mapRoute(RoutePattern.SETTINGS_LEGACY,
          '_handleSettingsLegacyRoute', true);

      this._mapRoute(RoutePattern.SETTINGS, '_handleSettingsRoute', true);

      this._mapRoute(RoutePattern.REGISTER, '_handleRegisterRoute');

      this._mapRoute(RoutePattern.LOG_IN_OR_OUT, '_handlePassThroughRoute');

      this._mapRoute(RoutePattern.IMPROPERLY_ENCODED_PLUS,
          '_handleImproperlyEncodedPlusRoute');

      this._mapRoute(RoutePattern.PLUGIN_SCREEN, '_handlePluginScreen');

      this._mapRoute(RoutePattern.DOCUMENTATION_SEARCH_FILTER,
          '_handleDocumentationSearchRoute');

      // redirects /Documentation/q/* to /Documentation/q/filter:*
      this._mapRoute(RoutePattern.DOCUMENTATION_SEARCH,
          '_handleDocumentationSearchRedirectRoute');

      // Makes sure /Documentation/* links work (doin't return 404)
      this._mapRoute(RoutePattern.DOCUMENTATION,
          '_handleDocumentationRedirectRoute');

      // Note: this route should appear last so it only catches URLs unmatched
      // by other patterns.
      this._mapRoute(RoutePattern.DEFAULT, '_handleDefaultRoute');

      page.start();
    },

    /**
     * @param {!Object} data
     * @return {Promise|null} if handling the route involves asynchrony, then a
     *     promise is returned. Otherwise, synchronous handling returns null.
     */
    _handleRootRoute(data) {
      if (data.querystring.match(/^closeAfterLogin/)) {
        // Close child window on redirect after login.
        window.close();
        return null;
      }
      let hash = this._getHashFromCanonicalPath(data.canonicalPath);
      // For backward compatibility with GWT links.
      if (hash) {
        // In certain login flows the server may redirect to a hash without
        // a leading slash, which page.js doesn't handle correctly.
        if (hash[0] !== '/') {
          hash = '/' + hash;
        }
        if (hash.includes('/ /') && data.canonicalPath.includes('/+/')) {
          // Path decodes all '+' to ' ' -- this breaks project-based URLs.
          // See Issue 6888.
          hash = hash.replace('/ /', '/+/');
        }
        const base = this.getBaseUrl();
        let newUrl = base + hash;
        if (hash.startsWith('/VE/')) {
          newUrl = base + '/settings' + hash;
        }
        this._redirect(newUrl);
        return null;
      }
      return this.$.restAPI.getLoggedIn().then(loggedIn => {
        if (loggedIn) {
          this._redirect('/dashboard/self');
        } else {
          this._redirect('/q/status:open');
        }
      });
    },

    /**
     * Decode an application/x-www-form-urlencoded string.
     *
     * @param {string} qs The application/x-www-form-urlencoded string.
     * @return {string} The decoded string.
     */
    _decodeQueryString(qs) {
      return decodeURIComponent(qs.replace(PLUS_PATTERN, ' '));
    },

    /**
     * Parse a query string (e.g. window.location.search) into an array of
     * name/value pairs.
     *
     * @param {string} qs The application/x-www-form-urlencoded query string.
     * @return {!Array<!Array<string>>} An array of name/value pairs, where each
     *     element is a 2-element array.
     */
    _parseQueryString(qs) {
      qs = qs.replace(QUESTION_PATTERN, '');
      if (!qs) {
        return [];
      }
      const params = [];
      qs.split('&').forEach(param => {
        const idx = param.indexOf('=');
        let name;
        let value;
        if (idx < 0) {
          name = this._decodeQueryString(param);
          value = '';
        } else {
          name = this._decodeQueryString(param.substring(0, idx));
          value = this._decodeQueryString(param.substring(idx + 1));
        }
        if (name) {
          params.push([name, value]);
        }
      });
      return params;
    },

    /**
     * Handle dashboard routes. These may be user, or project dashboards.
     *
     * @param {!Object} data The parsed route data.
     */
    _handleDashboardRoute(data) {
      // User dashboard. We require viewing user to be logged in, else we
      // redirect to login for self dashboard or simple owner search for
      // other user dashboard.
      return this.$.restAPI.getLoggedIn().then(loggedIn => {
        if (!loggedIn) {
          if (data.params[0].toLowerCase() === 'self') {
            this._redirectToLogin(data.canonicalPath);
          } else {
            this._redirect('/q/owner:' + encodeURIComponent(data.params[0]));
          }
        } else {
          this._setParams({
            view: Gerrit.Nav.View.DASHBOARD,
            user: data.params[0],
          });
        }
      });
    },

    /**
     * Handle custom dashboard routes.
     *
     * @param {!Object} data The parsed route data.
     * @param {string=} opt_qs Optional query string associated with the route.
     *     If not given, window.location.search is used. (Used by tests).
     */
    _handleCustomDashboardRoute(data, opt_qs) {
      // opt_qs may be provided by a test, and it may have a falsy value
      const qs = opt_qs !== undefined ? opt_qs : window.location.search;
      const queryParams = this._parseQueryString(qs);
      let title = 'Custom Dashboard';
      const titleParam = queryParams.find(
          elem => elem[0].toLowerCase() === 'title');
      if (titleParam) {
        title = titleParam[1];
      }
      // Dashboards support a foreach param which adds a base query to any
      // additional query.
      const forEachParam = queryParams.find(
          elem => elem[0].toLowerCase() === 'foreach');
      let forEachQuery = null;
      if (forEachParam) {
        forEachQuery = forEachParam[1];
      }
      const sectionParams = queryParams.filter(
          elem => elem[0] && elem[1] && elem[0].toLowerCase() !== 'title'
          && elem[0].toLowerCase() !== 'foreach');
      const sections = sectionParams.map(elem => {
        const query = forEachQuery ? `${forEachQuery} ${elem[1]}` : elem[1];
        return {
          name: elem[0],
          query,
        };
      });

      if (sections.length > 0) {
        // Custom dashboard view.
        this._setParams({
          view: Gerrit.Nav.View.DASHBOARD,
          user: 'self',
          sections,
          title,
        });
        return Promise.resolve();
      }

      // Redirect /dashboard/ -> /dashboard/self.
      this._redirect('/dashboard/self');
      return Promise.resolve();
    },

    _handleProjectDashboardRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.DASHBOARD,
        project: data.params[0],
        dashboard: decodeURIComponent(data.params[1]),
      });
    },

    _handleGroupInfoRoute(data) {
      this._redirect('/admin/groups/' + encodeURIComponent(data.params[0]));
    },

    _handleGroupSelfRedirectRoute(data) {
      this._redirect('/settings/#Groups');
    },

    _handleGroupRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.GROUP,
        groupId: data.params[0],
      });
    },

    _handleGroupAuditLogRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.GROUP,
        detail: Gerrit.Nav.GroupDetailView.LOG,
        groupId: data.params[0],
      });
    },

    _handleGroupMembersRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.GROUP,
        detail: Gerrit.Nav.GroupDetailView.MEMBERS,
        groupId: data.params[0],
      });
    },

    _handleGroupListOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-admin-group-list',
        offset: data.params[1] || 0,
        filter: null,
        openCreateModal: data.hash === 'create',
      });
    },

    _handleGroupListFilterOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-admin-group-list',
        offset: data.params.offset,
        filter: data.params.filter,
      });
    },

    _handleGroupListFilterRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-admin-group-list',
        filter: data.params.filter || null,
      });
    },

    _handleProjectsOldRoute(data) {
      let params = '';
      if (data.params[1]) {
        params = encodeURIComponent(data.params[1]);
        if (data.params[1].includes(',')) {
          params =
              encodeURIComponent(data.params[1]).replace('%2C', ',');
        }
      }

      this._redirect(`/admin/repos/${params}`);
    },

    _handleRepoCommandsRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.COMMANDS,
        repo: data.params[0],
      });
    },

    _handleRepoAccessRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.ACCESS,
        repo: data.params[0],
      });
    },

    _handleRepoDashboardsRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.DASHBOARDS,
        repo: data.params[0],
      });
    },

    _handleBranchListOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.BRANCHES,
        repo: data.params[0],
        offset: data.params[2] || 0,
        filter: null,
      });
    },

    _handleBranchListFilterOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.BRANCHES,
        repo: data.params.repo,
        offset: data.params.offset,
        filter: data.params.filter,
      });
    },

    _handleBranchListFilterRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.BRANCHES,
        repo: data.params.repo,
        filter: data.params.filter || null,
      });
    },

    _handleTagListOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.TAGS,
        repo: data.params[0],
        offset: data.params[2] || 0,
        filter: null,
      });
    },

    _handleTagListFilterOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.TAGS,
        repo: data.params.repo,
        offset: data.params.offset,
        filter: data.params.filter,
      });
    },

    _handleTagListFilterRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.TAGS,
        repo: data.params.repo,
        filter: data.params.filter || null,
      });
    },

    _handleRepoListOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-repo-list',
        offset: data.params[1] || 0,
        filter: null,
        openCreateModal: data.hash === 'create',
      });
    },

    _handleRepoListFilterOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-repo-list',
        offset: data.params.offset,
        filter: data.params.filter,
      });
    },

    _handleRepoListFilterRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-repo-list',
        filter: data.params.filter || null,
      });
    },

    _handleCreateProjectRoute(data) {
      // Redirects the legacy route to the new route, which displays the project
      // list with a hash 'create'.
      this._redirect('/admin/repos#create');
    },

    _handleCreateGroupRoute(data) {
      // Redirects the legacy route to the new route, which displays the group
      // list with a hash 'create'.
      this._redirect('/admin/groups#create');
    },

    _handleRepoRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        repo: data.params[0],
      });
    },

    _handlePluginListOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-plugin-list',
        offset: data.params[1] || 0,
        filter: null,
      });
    },

    _handlePluginListFilterOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-plugin-list',
        offset: data.params.offset,
        filter: data.params.filter,
      });
    },

    _handlePluginListFilterRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-plugin-list',
        filter: data.params.filter || null,
      });
    },

    _handlePluginListRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-plugin-list',
      });
    },

    _handleQueryRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.SEARCH,
        query: data.params[0],
        offset: data.params[2],
      });
    },

    _handleQueryLegacySuffixRoute(ctx) {
      this._redirect(ctx.path.replace(LEGACY_QUERY_SUFFIX_PATTERN, ''));
    },

    _handleChangeNumberLegacyRoute(ctx) {
      this._redirect('/c/' + encodeURIComponent(ctx.params[0]));
    },

    _handleChangeRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      const params = {
        project: ctx.params[0],
        changeNum: ctx.params[1],
        basePatchNum: ctx.params[4],
        patchNum: ctx.params[6],
        view: Gerrit.Nav.View.CHANGE,
      };

      this._redirectOrNavigate(params);
    },

    _handleDiffRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      const params = {
        project: ctx.params[0],
        changeNum: ctx.params[1],
        basePatchNum: ctx.params[4],
        patchNum: ctx.params[6],
        path: ctx.params[8],
        view: Gerrit.Nav.View.DIFF,
      };

      const address = this._parseLineAddress(ctx.hash);
      if (address) {
        params.leftSide = address.leftSide;
        params.lineNum = address.lineNum;
      }

      this._redirectOrNavigate(params);
    },

    _handleChangeLegacyRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      const params = {
        changeNum: ctx.params[0],
        basePatchNum: ctx.params[3],
        patchNum: ctx.params[5],
        view: Gerrit.Nav.View.CHANGE,
        querystring: ctx.querystring,
      };

      this._normalizeLegacyRouteParams(params);
    },

    _handleLegacyLinenum(ctx) {
      this._redirect(ctx.path.replace(LEGACY_LINENUM_PATTERN, '#$1'));
    },

    _handleDiffLegacyRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      const params = {
        changeNum: ctx.params[0],
        basePatchNum: ctx.params[2],
        patchNum: ctx.params[4],
        path: ctx.params[5],
        view: Gerrit.Nav.View.DIFF,
      };

      const address = this._parseLineAddress(ctx.hash);
      if (address) {
        params.leftSide = address.leftSide;
        params.lineNum = address.lineNum;
      }

      this._normalizeLegacyRouteParams(params);
    },

    _handleDiffEditRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      this._redirectOrNavigate({
        project: ctx.params[0],
        changeNum: ctx.params[1],
        patchNum: ctx.params[2],
        path: ctx.params[3],
        view: Gerrit.Nav.View.EDIT,
      });
    },

    _handleChangeEditRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      this._redirectOrNavigate({
        project: ctx.params[0],
        changeNum: ctx.params[1],
        patchNum: ctx.params[3],
        view: Gerrit.Nav.View.CHANGE,
        edit: true,
      });
    },

    /**
     * Normalize the patch range params for a the change or diff view and
     * redirect if URL upgrade is needed.
     */
    _redirectOrNavigate(params) {
      const needsRedirect = this._normalizePatchRangeParams(params);
      if (needsRedirect) {
        this._redirect(this._generateUrl(params));
      } else {
        this._setParams(params);
      }
    },

    _handleAgreementsRoute() {
      this._redirect('/settings/#Agreements');
    },

    _handleNewAgreementsRoute(data) {
      data.params.view = Gerrit.Nav.View.AGREEMENTS;
      this._setParams(data.params);
    },

    _handleSettingsLegacyRoute(data) {
      // email tokens may contain '+' but no space.
      // The parameter parsing replaces all '+' with a space,
      // undo that to have valid tokens.
      const token = data.params[0].replace(/ /g, '+');
      this._setParams({
        view: Gerrit.Nav.View.SETTINGS,
        emailToken: token,
      });
    },

    _handleSettingsRoute(data) {
      this._setParams({view: Gerrit.Nav.View.SETTINGS});
    },

    _handleRegisterRoute(ctx) {
      this._setParams({justRegistered: true});
      let path = ctx.params[0] || '/';

      // Prevent redirect looping.
      if (path.startsWith('/register')) { path = '/'; }

      if (path[0] !== '/') { return; }
      this._redirect(this.getBaseUrl() + path);
    },

    /**
     * Handler for routes that should pass through the router and not be caught
     * by the catchall _handleDefaultRoute handler.
     */
    _handlePassThroughRoute() {
      location.reload();
    },


    /**
     * URL may sometimes have /+/ encoded to / /.
     * Context: Issue 6888, Issue 7100
     */
    _handleImproperlyEncodedPlusRoute(ctx) {
      let hash = this._getHashFromCanonicalPath(ctx.canonicalPath);
      if (hash.length) { hash = '#' + hash; }
      this._redirect(`/c/${ctx.params[0]}/+/${ctx.params[1]}${hash}`);
    },

    _handlePluginScreen(ctx) {
      const view = Gerrit.Nav.View.PLUGIN_SCREEN;
      const plugin = ctx.params[0];
      const screen = ctx.params[1];
      this._setParams({view, plugin, screen});
    },

    _handleDocumentationSearchRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.DOCUMENTATION_SEARCH,
        filter: data.params.filter || null,
      });
    },

    _handleDocumentationSearchRedirectRoute(data) {
      this._redirect('/Documentation/q/filter:' +
          encodeURIComponent(data.params[0]));
    },

    _handleDocumentationRedirectRoute(data) {
      if (data.params[1]) {
        location.reload();
      } else {
        // Redirect /Documentation to /Documentation/index.html
        this._redirect('/Documentation/index.html');
      }
    },

    /**
     * Catchall route for when no other route is matched.
     */
    _handleDefaultRoute() {
      if (this._isInitialLoad) {
        // Server recognized this route as polygerrit, so we show 404.
        this._show404();
      } else {
        // Route can be recognized by server, so we pass it to server.
        this._handlePassThroughRoute();
      }
    },

    _show404() {
      // Note: the app's 404 display is tightly-coupled with catching 404
      // network responses, so we simulate a 404 response status to display it.
      // TODO: Decouple the gr-app error view from network responses.
      this._appElement().dispatchEvent(new CustomEvent('page-error',
          {detail: {response: {status: 404}}}));
    },
  });
})();
