// Copyright (C) 2019 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 {Engine} from '../common/engine';
import {
  LogBounds,
  LogBoundsKey,
  LogEntries,
  LogEntriesKey,
  LogExistsKey,
} from '../common/logs';
import {NUM, STR} from '../common/query_result';
import {escapeGlob, escapeQuery} from '../common/query_utils';
import {LogFilteringCriteria} from '../common/state';
import {fromNs, TimeSpan, toNsCeil, toNsFloor} from '../common/time';
import {globals} from '../frontend/globals';
import {publishTrackData} from '../frontend/publish';

import {Controller} from './controller';

async function updateLogBounds(
    engine: Engine, span: TimeSpan): Promise<LogBounds> {
  const vizStartNs = toNsFloor(span.start);
  const vizEndNs = toNsCeil(span.end);

  const countResult = await engine.query(`select
      ifnull(min(ts), 0) as minTs,
      ifnull(max(ts), 0) as maxTs,
      count(ts) as countTs
     from filtered_logs
        where ts >= ${vizStartNs}
        and ts <= ${vizEndNs}`);

  const countRow = countResult.firstRow({minTs: NUM, maxTs: NUM, countTs: NUM});

  const firstRowNs = countRow.minTs;
  const lastRowNs = countRow.maxTs;
  const total = countRow.countTs;

  const minResult = await engine.query(`
     select ifnull(max(ts), 0) as maxTs from filtered_logs where ts < ${
      vizStartNs}`);
  const startNs = minResult.firstRow({maxTs: NUM}).maxTs;

  const maxResult = await engine.query(`
     select ifnull(min(ts), 0) as minTs from filtered_logs where ts > ${
      vizEndNs}`);
  const endNs = maxResult.firstRow({minTs: NUM}).minTs;

  const startTs = startNs ? fromNs(startNs) : 0;
  const endTs = endNs ? fromNs(endNs) : Number.MAX_SAFE_INTEGER;
  const firstRowTs = firstRowNs ? fromNs(firstRowNs) : endTs;
  const lastRowTs = lastRowNs ? fromNs(lastRowNs) : startTs;
  return {
    startTs,
    endTs,
    firstRowTs,
    lastRowTs,
    total,
  };
}

async function updateLogEntries(
    engine: Engine, span: TimeSpan, pagination: Pagination):
    Promise<LogEntries> {
  const vizStartNs = toNsFloor(span.start);
  const vizEndNs = toNsCeil(span.end);
  const vizSqlBounds = `ts >= ${vizStartNs} and ts <= ${vizEndNs}`;

  const rowsResult = await engine.query(`
        select
          ts,
          prio,
          ifnull(tag, '[NULL]') as tag,
          ifnull(msg, '[NULL]') as msg,
          is_msg_highlighted as isMsgHighlighted,
          is_process_highlighted as isProcessHighlighted,
          ifnull(process_name, '') as processName
        from filtered_logs
        where ${vizSqlBounds}
        order by ts
        limit ${pagination.start}, ${pagination.count}
    `);

  const timestamps = [];
  const priorities = [];
  const tags = [];
  const messages = [];
  const isHighlighted = [];
  const processName = [];

  const it = rowsResult.iter({
    ts: NUM,
    prio: NUM,
    tag: STR,
    msg: STR,
    isMsgHighlighted: NUM,
    isProcessHighlighted: NUM,
    processName: STR,
  });
  for (; it.valid(); it.next()) {
    timestamps.push(it.ts);
    priorities.push(it.prio);
    tags.push(it.tag);
    messages.push(it.msg);
    isHighlighted.push(
        it.isMsgHighlighted === 1 || it.isProcessHighlighted === 1);
    processName.push(it.processName);
  }

  return {
    offset: pagination.start,
    timestamps,
    priorities,
    tags,
    messages,
    isHighlighted,
    processName,
  };
}

class Pagination {
  private _offset: number;
  private _count: number;

  constructor(offset: number, count: number) {
    this._offset = offset;
    this._count = count;
  }

  get start() {
    return this._offset;
  }

  get count() {
    return this._count;
  }

  get end() {
    return this._offset + this._count;
  }

  contains(other: Pagination): boolean {
    return this.start <= other.start && other.end <= this.end;
  }

  grow(n: number): Pagination {
    const newStart = Math.max(0, this.start - n / 2);
    const newCount = this.count + n;
    return new Pagination(newStart, newCount);
  }
}

export interface LogsControllerArgs {
  engine: Engine;
}

/**
 * LogsController looks at three parts of the state:
 * 1. The visible trace window
 * 2. The requested offset and count the log lines to display
 * 3. The log filtering criteria.
 * And keeps two bits of published information up to date:
 * 1. The total number of log messages in visible range
 * 2. The logs lines that should be displayed
 * Based on the log filtering criteria, it also builds the filtered_logs view
 * and keeps it up to date.
 */
export class LogsController extends Controller<'main'> {
  private engine: Engine;
  private span: TimeSpan;
  private pagination: Pagination;
  private hasLogs = false;
  private logFilteringCriteria?: LogFilteringCriteria;
  private requestingData = false;
  private queuedRunRequest = false;

  constructor(args: LogsControllerArgs) {
    super('main');
    this.engine = args.engine;
    this.span = new TimeSpan(0, 10);
    this.pagination = new Pagination(0, 0);
    this.hasAnyLogs().then((exists) => {
      this.hasLogs = exists;
      publishTrackData({
        id: LogExistsKey,
        data: {
          exists,
        },
      });
    });
  }

  async hasAnyLogs() {
    const result = await this.engine.query(`
      select count(*) as cnt from android_logs
    `);
    return result.firstRow({cnt: NUM}).cnt > 0;
  }

  run() {
    if (!this.hasLogs) return;
    if (this.requestingData) {
      this.queuedRunRequest = true;
      return;
    }
    this.requestingData = true;
    this.updateLogTracks().finally(() => {
      this.requestingData = false;
      if (this.queuedRunRequest) {
        this.queuedRunRequest = false;
        this.run();
      }
    });
  }

  private async updateLogTracks() {
    const traceTime = globals.state.frontendLocalState.visibleState;
    const newSpan = new TimeSpan(traceTime.startSec, traceTime.endSec);
    const oldSpan = this.span;

    const pagination = globals.state.logsPagination;
    // This can occur when loading old traces.
    // TODO(hjd): Fix the problem of accessing state from a previous version of
    // the UI in a general way.
    if (pagination === undefined) {
      return;
    }

    const {offset, count} = pagination;
    const requestedPagination = new Pagination(offset, count);
    const oldPagination = this.pagination;

    const newFilteringCriteria =
        this.logFilteringCriteria !== globals.state.logFilteringCriteria;
    const needBoundsUpdate = !oldSpan.equals(newSpan) || newFilteringCriteria;
    const needEntriesUpdate =
        !oldPagination.contains(requestedPagination) || needBoundsUpdate;

    if (newFilteringCriteria) {
      this.logFilteringCriteria = globals.state.logFilteringCriteria;
      await this.engine.query('drop view if exists filtered_logs');

      const globMatch = LogsController.composeGlobMatch(
          this.logFilteringCriteria.hideNonMatching,
          this.logFilteringCriteria.textEntry);
      let selectedRows = `select prio, ts, tag, msg,
          process.name as process_name, ${globMatch}
          from android_logs
          left join thread using(utid)
          left join process using(upid)
          where prio >= ${this.logFilteringCriteria.minimumLevel}`;
      if (this.logFilteringCriteria.tags.length) {
        selectedRows += ` and tag in (${
            LogsController.serializeTags(this.logFilteringCriteria.tags)})`;
      }

      // We extract only the rows which will be visible.
      await this.engine.query(`create view filtered_logs as select *
        from (${selectedRows})
        where is_msg_chosen is 1 or is_process_chosen is 1`);
    }

    if (needBoundsUpdate) {
      this.span = newSpan;
      const logBounds = await updateLogBounds(this.engine, newSpan);
      publishTrackData({
        id: LogBoundsKey,
        data: logBounds,
      });
    }

    if (needEntriesUpdate) {
      this.pagination = requestedPagination.grow(100);
      const logEntries =
          await updateLogEntries(this.engine, newSpan, this.pagination);
      publishTrackData({
        id: LogEntriesKey,
        data: logEntries,
      });
    }
  }

  private static serializeTags(tags: string[]) {
    return tags.map((tag) => escapeQuery(tag)).join();
  }

  private static composeGlobMatch(isCollaped: boolean, textEntry: string) {
    if (isCollaped) {
      // If the entries are collapsed, we won't highlight any lines.
      return `msg glob ${escapeGlob(textEntry)} as is_msg_chosen,
        (process.name is not null and process.name glob ${
          escapeGlob(textEntry)}) as is_process_chosen,
        0 as is_msg_highlighted,
        0 as is_process_highlighted`;
    } else if (!textEntry) {
      // If there is no text entry, we will show all lines, but won't highlight.
      // any.
      return `1 as is_msg_chosen,
        1 as is_process_chosen,
        0 as is_msg_highlighted,
        0 as is_process_highlighted`;
    } else {
      return `1 as is_msg_chosen,
        1 as is_process_chosen,
        msg glob ${escapeGlob(textEntry)} as is_msg_highlighted,
        (process.name is not null and process.name glob ${
          escapeGlob(textEntry)}) as is_process_highlighted`;
    }
  }
}
