// Copyright (C) 2018 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 m from 'mithril';

import {assertExists, assertTrue} from '../base/logging';
import {
  oneOf,
  optBool,
  optStr,
  record,
  runValidator,
  ValidatedType,
} from '../controller/validators';

import {PageAttrs} from './pages';

export const ROUTE_PREFIX = '#!';
const DEFAULT_ROUTE = '/';

const modes = ['embedded', undefined] as const;
type Mode = typeof modes[number];

// The set of args that can be set on the route via #!/page?a=1&b2.
// Route args are orthogonal to pages (i.e. should NOT make sense only in a
// only within a specific page, use /page/subpages for that).
// Args are !== the querystring (location.search) which is sent to the
// server. The route args are NOT sent to the HTTP server.
// Given this URL:
// http://host/?foo=1&bar=2#!/page/subpage?local_cache_key=a0b1&baz=3.
//
// location.search = 'foo=1&bar=2'.
//   This is seen by the HTTP server. We really don't use querystrings as the
//   perfetto UI is client only.
//
// location.hash = '#!/page/subpage?local_cache_key=a0b1'.
//   This is client-only. All the routing logic in the Perfetto UI uses only
//   this.

const routeArgs = record({
  // The local_cache_key is special and is persisted across navigations.
  local_cache_key: optStr,

  // These are transient and are really set only on startup.

  // Are we loading a trace via ABT.
  openFromAndroidBugTool: optBool,

  // For permalink hash.
  s: optStr,

  // DEPRECATED: for #!/record?p=cpu subpages (b/191255021).
  p: optStr,

  // For fetching traces from Cloud Storage.
  url: optStr,

  // For the 'mode' of the UI. For example when the mode is 'embedded'
  // some features are disabled.
  mode: oneOf<Mode>(modes, undefined),

  // Should we hide the sidebar?
  hideSidebar: optBool,

  // Deep link support
  ts: optStr,
  dur: optStr,
  tid: optStr,
  pid: optStr,
  query: optStr,
});
type RouteArgs = ValidatedType<typeof routeArgs>;

// A broken down representation of a route.
// For instance: #!/record/gpu?local_cache_key=a0b1
// becomes: {page: '/record', subpage: '/gpu', args: {local_cache_key: 'a0b1'}}
export interface Route {
  page: string;
  subpage: string;
  fragment: string;
  args: RouteArgs;
}

export interface RoutesMap {
  [key: string]: m.Component<PageAttrs>;
}

// This router does two things:
// 1) Maps fragment paths (#!/page/subpage) to Mithril components.
// The route map is passed to the ctor and is later used when calling the
// resolve() method.
//
// 2) Handles the (optional) args, e.g. #!/page?arg=1&arg2=2.
// Route args are carry information that is orthogonal to the page (e.g. the
// trace id).
// local_cache_key has some special treatment: once a URL has a local_cache_key,
// it gets automatically appended to further navigations that don't have one.
// For instance if the current url is #!/viewer?local_cache_key=1234 and a later
// action (either user-initiated or code-initited) navigates to #!/info, the
// rotuer will automatically replace the history entry with
// #!/info?local_cache_key=1234.
// This is to keep propagating the trace id across page changes, for handling
// tab discards (b/175041881).
//
// This class does NOT deal with the "load a trace when the url contains ?url=
// or ?local_cache_key=". That logic lives in trace_url_handler.ts, which is
// triggered by Router.onRouteChanged().
export class Router {
  private readonly recentChanges: number[] = [];
  private routes: RoutesMap;

  // frontend/index.ts calls maybeOpenTraceFromRoute() + redraw here.
  // This event is decoupled for testing and to avoid circular deps.
  onRouteChanged: (route: Route) => (void) = () => {};

  constructor(routes: RoutesMap) {
    assertExists(routes[DEFAULT_ROUTE]);
    this.routes = routes;
    window.onhashchange = (e: HashChangeEvent) => this.onHashChange(e);
    const route = Router.parseUrl(window.location.href);
    this.onRouteChanged(route);
  }

  private onHashChange(e: HashChangeEvent) {
    this.crashIfLivelock();

    const oldRoute = Router.parseUrl(e.oldURL);
    const newRoute = Router.parseUrl(e.newURL);

    if (newRoute.args.local_cache_key === undefined &&
        oldRoute.args.local_cache_key) {
      // Propagate `local_cache_key across` navigations. When a trace is loaded,
      // the URL becomes #!/viewer?local_cache_key=123. `local_cache_key` allows
      // reopening the trace from cache in the case of a reload or discard.
      // When using the UI we can hit "bare" links (e.g. just '#!/info') which
      // don't have the trace_uuid:
      // - When clicking on an <a> element from the sidebar.
      // - When the code calls Router.navigate().
      // - When the user pastes a URL from docs page.
      // In all these cases we want to keep propagating the `local_cache_key`.
      // We do so by re-setting the `local_cache_key` and doing a
      // location.replace which overwrites the history entry (note
      // location.replace is NOT just a String.replace operation).
      newRoute.args.local_cache_key = oldRoute.args.local_cache_key;
    }

    const args = m.buildQueryString(newRoute.args);
    let normalizedFragment = `#!${newRoute.page}${newRoute.subpage}`;
    if (args.length) {
      normalizedFragment += `?${args}`;
    }
    if (newRoute.fragment) {
      normalizedFragment += `#${newRoute.fragment}`;
    }

    if (!e.newURL.endsWith(normalizedFragment)) {
      location.replace(normalizedFragment);
      return;
    }

    this.onRouteChanged(newRoute);
  }

  // Returns the component for the current route in the URL.
  // If no route matches the URL, returns a component corresponding to
  // |this.defaultRoute|.
  resolve(): m.Vnode<PageAttrs> {
    const route = Router.parseFragment(location.hash);
    let component = this.routes[route.page];
    if (component === undefined) {
      component = assertExists(this.routes[DEFAULT_ROUTE]);
    }
    return m(component, {subpage: route.subpage} as PageAttrs);
  }

  static navigate(newHash: string) {
    assertTrue(newHash.startsWith(ROUTE_PREFIX));
    window.location.hash = newHash;
  }

  // Breaks down a fragment into a Route object.
  // Sample input:
  // '#!/record/gpu?local_cache_key=abcd-1234#myfragment'
  // Sample output:
  // {
  //  page: '/record',
  //  subpage: '/gpu',
  //  fragment: 'myfragment',
  //  args: {local_cache_key: 'abcd-1234'}
  // }
  static parseFragment(hash: string): Route {
    if (hash.startsWith(ROUTE_PREFIX)) {
      hash = hash.substring(ROUTE_PREFIX.length);
    } else {
      hash = '';
    }

    const url = new URL(`https://example.com${hash}`);

    const path = url.pathname;
    let page = path;
    let subpage = '';
    const splittingPoint = path.indexOf('/', 1);
    if (splittingPoint > 0) {
      page = path.substring(0, splittingPoint);
      subpage = path.substring(splittingPoint);
    }
    if (page === '/') {
      page = '';
    }

    let rawArgs = {};
    if (url.search) {
      rawArgs = Router.parseQueryString(url.search);
    }

    const args = runValidator(routeArgs, rawArgs).result;

    // Javascript sadly distinguishes between foo[bar] === undefined
    // and foo[bar] is not set at all. Here we need the second case to
    // avoid making the URL ugly.
    for (const key of Object.keys(args)) {
      if ((args as any)[key] === undefined) {
        delete (args as any)[key];
      }
    }

    let fragment = url.hash;
    if (fragment.startsWith('#')) {
      fragment = fragment.substring(1);
    }

    return {page, subpage, args, fragment};
  }

  private static parseQueryString(query: string) {
    // TODO(hjd): Use replaceAll when we have updated to es2021.
    query = query.replace(/\+/g, ' ');
    return m.parseQueryString(query);
  }

  private static parseSearchParams(url: string): RouteArgs {
    const query = (new URL(url)).search;
    const rawArgs = Router.parseQueryString(query);
    const args = runValidator(routeArgs, rawArgs).result;

    // Javascript sadly distinguishes between foo[bar] === undefined
    // and foo[bar] is not set at all. Here we need the second case to
    // avoid making the URL ugly.
    for (const key of Object.keys(args)) {
      if ((args as any)[key] === undefined) {
        delete (args as any)[key];
      }
    }

    return args;
  }

  // Like parseFragment() but takes a full URL.
  static parseUrl(url: string): Route {
    const searchArgs = Router.parseSearchParams(url);

    const hashPos = url.indexOf('#');
    const fragment = hashPos < 0 ? '' : url.substring(hashPos);
    const route = Router.parseFragment(fragment);
    route.args = Object.assign({}, searchArgs, route.args);

    return route;
  }

  // Throws if EVENT_LIMIT onhashchange events occur within WINDOW_MS.
  private crashIfLivelock() {
    const WINDOW_MS = 1000;
    const EVENT_LIMIT = 20;
    const now = Date.now();
    while (this.recentChanges.length > 0 &&
           now - this.recentChanges[0] > WINDOW_MS) {
      this.recentChanges.shift();
    }
    this.recentChanges.push(now);
    if (this.recentChanges.length > EVENT_LIMIT) {
      throw new Error('History rewriting livelock');
    }
  }
}
