// 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 {BigintMath} from '../base/bigint_math';
import {Engine} from '../common/engine';
import {
  LogBounds,
  LogBoundsKey,
  LogEntries,
  LogEntriesKey,
  LogExistsKey,
} from '../common/logs';
import {LONG, LONG_NULL, NUM, STR} from '../common/query_result';
import {escapeGlob, escapeQuery} from '../common/query_utils';
import {LogFilteringCriteria} from '../common/state';
import {Span} from '../common/time';
import {
  TPTime,
  TPTimeSpan,
} from '../common/time';
import {globals} from '../frontend/globals';
import {publishTrackData} from '../frontend/publish';

import {Controller} from './controller';

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

  const vizFilter = `ts between ${vizStartNs} and ${vizEndNs}`;

  const result = await engine.query(`select
      min(ts) as minTs,
      max(ts) as maxTs,
      min(case when ${vizFilter} then ts end) as minVizTs,
      max(case when ${vizFilter} then ts end) as maxVizTs,
      count(case when ${vizFilter} then ts end) as countTs
    from filtered_logs`);

  const data = result.firstRow({
    minTs: LONG_NULL,
    maxTs: LONG_NULL,
    minVizTs: LONG_NULL,
    maxVizTs: LONG_NULL,
    countTs: NUM,
  });

  const firstLogTs = data.minTs ?? 0n;
  const lastLogTs = data.maxTs ?? BigintMath.INT64_MAX;

  const bounds: LogBounds = {
    firstLogTs,
    lastLogTs,
    firstVisibleLogTs: data.minVizTs ?? firstLogTs,
    lastVisibleLogTs: data.maxVizTs ?? lastLogTs,
    totalVisibleLogs: data.countTs,
  };

  return bounds;
}

async function updateLogEntries(
    engine: Engine, span: Span<TPTime>, pagination: Pagination):
    Promise<LogEntries> {
  const vizStartNs = span.start;
  const vizEndNs = 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: LONG,
    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: Span<TPTime>;
  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 TPTimeSpan(0n, BigInt(10e9));
    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 newSpan = globals.stateVisibleTime();
    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`;
    }
  }
}
