// Copyright (C) 2020 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 {BigintMath} from '../base/bigint_math';
import {copyToClipboard} from '../base/clipboard';
import {isString} from '../base/object_utils';
import {Time} from '../base/time';
import {Actions} from '../common/actions';
import {QueryResponse} from '../common/queries';
import {Row} from '../trace_processor/query_result';
import {Anchor} from '../widgets/anchor';
import {Button} from '../widgets/button';
import {Callout} from '../widgets/callout';
import {DetailsShell} from '../widgets/details_shell';

import {queryResponseToClipboard} from './clipboard';
import {downloadData} from './download_utils';
import {globals} from './globals';
import {Router} from './router';
import {reveal} from './scroll_helper';

interface QueryTableRowAttrs {
  row: Row;
  columns: string[];
}

type Numeric = bigint | number;

function isIntegral(x: Row[string]): x is Numeric {
  return (
    typeof x === 'bigint' || (typeof x === 'number' && Number.isInteger(x))
  );
}

function hasTs(row: Row): row is Row & {ts: Numeric} {
  return 'ts' in row && isIntegral(row.ts);
}

function hasDur(row: Row): row is Row & {dur: Numeric} {
  return 'dur' in row && isIntegral(row.dur);
}

function hasTrackId(row: Row): row is Row & {track_id: Numeric} {
  return 'track_id' in row && isIntegral(row.track_id);
}

function hasType(row: Row): row is Row & {type: string} {
  return 'type' in row && isString(row.type);
}

function hasId(row: Row): row is Row & {id: Numeric} {
  return 'id' in row && isIntegral(row.id);
}

function hasSliceId(row: Row): row is Row & {slice_id: Numeric} {
  return 'slice_id' in row && isIntegral(row.slice_id);
}

// These are properties that a row should have in order to be "slice-like",
// insofar as it represents a time range and a track id which can be revealed
// or zoomed-into on the timeline.
type Sliceish = {
  ts: Numeric;
  dur: Numeric;
  track_id: Numeric;
};

export function isSliceish(row: Row): row is Row & Sliceish {
  return hasTs(row) && hasDur(row) && hasTrackId(row);
}

// Attempts to extract a slice ID from a row, or undefined if none can be found
export function getSliceId(row: Row): number | undefined {
  if (hasType(row) && row.type.includes('slice')) {
    if (hasId(row)) {
      return Number(row.id);
    }
  } else {
    if (hasSliceId(row)) {
      return Number(row.slice_id);
    }
  }
  return undefined;
}

class QueryTableRow implements m.ClassComponent<QueryTableRowAttrs> {
  view(vnode: m.Vnode<QueryTableRowAttrs>) {
    const {row, columns} = vnode.attrs;
    const cells = columns.map((col) => this.renderCell(col, row[col]));

    // TODO(dproy): Make click handler work from analyze page.
    if (
      Router.parseUrl(window.location.href).page === '/viewer' &&
      isSliceish(row)
    ) {
      return m(
        'tr',
        {
          onclick: () => this.selectAndRevealSlice(row, false),
          // TODO(altimin): Consider improving the logic here (e.g. delay?) to
          // account for cases when dblclick fires late.
          ondblclick: () => this.selectAndRevealSlice(row, true),
          clickable: true,
          title: 'Go to slice',
        },
        cells,
      );
    } else {
      return m('tr', cells);
    }
  }

  private renderCell(name: string, value: Row[string]) {
    if (value instanceof Uint8Array) {
      return m('td', this.renderBlob(name, value));
    } else {
      return m('td', `${value}`);
    }
  }

  private renderBlob(name: string, value: Uint8Array) {
    return m(
      Anchor,
      {
        onclick: () => downloadData(`${name}.blob`, value),
      },
      `Blob (${value.length} bytes)`,
    );
  }

  private selectAndRevealSlice(
    row: Row & Sliceish,
    switchToCurrentSelectionTab: boolean,
  ) {
    const trackId = Number(row.track_id);
    const sliceStart = Time.fromRaw(BigInt(row.ts));
    // row.dur can be negative. Clamp to 1ns.
    const sliceDur = BigintMath.max(BigInt(row.dur), 1n);
    const trackKey = globals.trackManager.trackKeyByTrackId.get(trackId);
    if (trackKey !== undefined) {
      reveal(trackKey, sliceStart, Time.add(sliceStart, sliceDur), true);
      const sliceId = getSliceId(row);
      if (sliceId !== undefined) {
        this.selectSlice(sliceId, trackKey, switchToCurrentSelectionTab);
      }
    }
  }

  private selectSlice(
    sliceId: number,
    trackKey: string,
    switchToCurrentSelectionTab: boolean,
  ) {
    const action = Actions.selectSlice({
      id: sliceId,
      trackKey,
      table: 'slice',
    });
    globals.makeSelection(action, {switchToCurrentSelectionTab});
  }
}

interface QueryTableContentAttrs {
  resp: QueryResponse;
}

class QueryTableContent implements m.ClassComponent<QueryTableContentAttrs> {
  private previousResponse?: QueryResponse;

  onbeforeupdate(vnode: m.CVnode<QueryTableContentAttrs>) {
    return vnode.attrs.resp !== this.previousResponse;
  }

  view(vnode: m.CVnode<QueryTableContentAttrs>) {
    const resp = vnode.attrs.resp;
    this.previousResponse = resp;
    const cols = [];
    for (const col of resp.columns) {
      cols.push(m('td', col));
    }
    const tableHeader = m('tr', cols);

    const rows = resp.rows.map((row) =>
      m(QueryTableRow, {row, columns: resp.columns}),
    );

    if (resp.error) {
      return m('.query-error', `SQL error: ${resp.error}`);
    } else {
      return m(
        'table.pf-query-table',
        m('thead', tableHeader),
        m('tbody', rows),
      );
    }
  }
}

interface QueryTableAttrs {
  query: string;
  resp?: QueryResponse;
  contextButtons?: m.Child[];
  fillParent: boolean;
}

export class QueryTable implements m.ClassComponent<QueryTableAttrs> {
  view({attrs}: m.CVnode<QueryTableAttrs>) {
    const {resp, query, contextButtons = [], fillParent} = attrs;

    return m(
      DetailsShell,
      {
        title: this.renderTitle(resp),
        description: query,
        buttons: this.renderButtons(query, contextButtons, resp),
        fillParent,
      },
      resp && this.renderTableContent(resp),
    );
  }

  renderTitle(resp?: QueryResponse) {
    if (!resp) {
      return 'Query - running';
    }
    const result = resp.error ? 'error' : `${resp.rows.length} rows`;
    return `Query result (${result}) - ${resp.durationMs.toLocaleString()}ms`;
  }

  renderButtons(
    query: string,
    contextButtons: m.Child[],
    resp?: QueryResponse,
  ) {
    return [
      contextButtons,
      m(Button, {
        label: 'Copy query',
        onclick: () => {
          copyToClipboard(query);
        },
      }),
      resp &&
        resp.error === undefined &&
        m(Button, {
          label: 'Copy result (.tsv)',
          onclick: () => {
            queryResponseToClipboard(resp);
          },
        }),
    ];
  }

  renderTableContent(resp: QueryResponse) {
    return m(
      '.pf-query-panel',
      resp.statementWithOutputCount > 1 &&
        m(
          '.pf-query-warning',
          m(
            Callout,
            {icon: 'warning'},
            `${resp.statementWithOutputCount} out of ${resp.statementCount} `,
            'statements returned a result. ',
            'Only the results for the last statement are displayed.',
          ),
        ),
      m(QueryTableContent, {resp}),
    );
  }
}
