// 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 {fromNs, TimeSpan} from '../common/time';

import {Controller} from './controller';
import {App} from './globals';

async function updateLogBounds(
    engine: Engine, span: TimeSpan): Promise<LogBounds> {
  const vizStartNs = Math.floor(span.start * 1e9);
  const vizEndNs = Math.ceil(span.end * 1e9);

  const countResult = await engine.queryOneRow(`
     select min(ts), max(ts), count(ts)
     from android_logs where ts >= ${vizStartNs} and ts <= ${vizEndNs}`);

  const firstRowNs = countResult[0];
  const lastRowNs = countResult[1];
  const total = countResult[2];

  const minResult = await engine.queryOneRow(`
     select max(ts) from android_logs where ts < ${vizStartNs}`);
  const startNs = minResult[0];

  const maxResult = await engine.queryOneRow(`
     select min(ts) from android_logs where ts > ${vizEndNs}`);
  const endNs = maxResult[0];

  const trace = await engine.getTraceTimeBounds();
  const startTs = startNs ? fromNs(startNs) : trace.start;
  const endTs = endNs ? fromNs(endNs) : trace.end;
  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 = Math.floor(span.start * 1e9);
  const vizEndNs = Math.ceil(span.end * 1e9);
  const vizSqlBounds = `ts >= ${vizStartNs} and ts <= ${vizEndNs}`;

  const rowsResult =
      await engine.query(`select ts, prio, tag, msg from android_logs
        where ${vizSqlBounds}
        order by ts
        limit ${pagination.start}, ${pagination.count}`);

  if (!rowsResult.numRecords) {
    return {
      offset: pagination.start,
      timestamps: [],
      priorities: [],
      tags: [],
      messages: [],
    };
  }

  const timestamps = rowsResult.columns[0].longValues! as number[];
  const priorities = rowsResult.columns[1].longValues! as number[];
  const tags = rowsResult.columns[2].stringValues!;
  const messages = rowsResult.columns[3].stringValues!;

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

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;
  app: App;
}

/**
 * LogsController looks at two parts of the state:
 * 1. The visible trace window
 * 2. The requested offset and count the log lines to display
 * 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
 */
export class LogsController extends Controller<'main'> {
  private app: App;
  private engine: Engine;
  private span: TimeSpan;
  private pagination: Pagination;

  constructor(args: LogsControllerArgs) {
    super('main');
    this.app = args.app;
    this.engine = args.engine;
    this.span = new TimeSpan(0, 10);
    this.pagination = new Pagination(0, 0);
    this.publishHasAnyLogs();
  }

  async publishHasAnyLogs() {
    const result = await this.engine.queryOneRow(`
      select count(*) from android_logs
    `);
    const exists = result[0] > 0;
    this.app.publish('TrackData', {
      id: LogExistsKey,
      data: {
        exists,
      },
    });
  }

  run() {
    const traceTime = this.app.state.frontendLocalState.visibleTraceTime;
    const newSpan = new TimeSpan(traceTime.startSec, traceTime.endSec);
    const oldSpan = this.span;

    const pagination = this.app.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 needSpanUpdate = !oldSpan.equals(newSpan);
    const needPaginationUpdate = !oldPagination.contains(requestedPagination);

    // TODO(hjd): We could waste a lot of time queueing useless updates here.
    // We should avoid enqueuing a request when one is in progress.
    if (needSpanUpdate) {
      this.span = newSpan;
      updateLogBounds(this.engine, newSpan).then(data => {
        if (!newSpan.equals(this.span)) return;
        this.app.publish('TrackData', {
          id: LogBoundsKey,
          data,
        });
      });
    }

    // TODO(hjd): We could waste a lot of time queueing useless updates here.
    // We should avoid enqueuing a request when one is in progress.
    if (needSpanUpdate || needPaginationUpdate) {
      this.pagination = requestedPagination.grow(100);

      updateLogEntries(this.engine, newSpan, this.pagination).then(data => {
        if (!this.pagination.contains(requestedPagination)) return;
        this.app.publish('TrackData', {
          id: LogEntriesKey,
          data,
        });
      });
    }

    return [];
  }
}
