// Copyright (C) 2022 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 {STAR} from './icons';

import {
  arrayOf,
  bool,
  record,
  runValidator,
  str,
  ValidatedType,
} from '../base/validators';
import {assertTrue} from '../base/logging';
import {Icon} from './widgets/icon';
import {raf} from '../core/raf_scheduler';

const QUERY_HISTORY_KEY = 'queryHistory';

export interface QueryHistoryComponentAttrs {
  runQuery: (query: string) => void;
}

export class QueryHistoryComponent implements
    m.ClassComponent<QueryHistoryComponentAttrs> {
  view({attrs}: m.CVnode<QueryHistoryComponentAttrs>): m.Child {
    const runQuery = attrs.runQuery;
    const unstarred: HistoryItemComponentAttrs[] = [];
    const starred: HistoryItemComponentAttrs[] = [];
    for (let i = queryHistoryStorage.data.length - 1; i >= 0; i--) {
      const entry = queryHistoryStorage.data[i];
      const arr = entry.starred ? starred : unstarred;
      arr.push({index: i, entry, runQuery});
    }
    return m(
        '.query-history',
        m('header.overview',
          `Query history (${queryHistoryStorage.data.length} queries)`),
        starred.map((attrs) => m(HistoryItemComponent, attrs)),
        unstarred.map((attrs) => m(HistoryItemComponent, attrs)));
  }
}

export interface HistoryItemComponentAttrs {
  index: number;
  entry: QueryHistoryEntry;
  runQuery: (query: string) => void;
}

export class HistoryItemComponent implements
    m.ClassComponent<HistoryItemComponentAttrs> {
  view(vnode: m.Vnode<HistoryItemComponentAttrs>): m.Child {
    const query = vnode.attrs.entry.query;
    return m(
        '.history-item',
        m('.history-item-buttons',
          m(
              'button',
              {
                onclick: () => {
                  queryHistoryStorage.setStarred(
                      vnode.attrs.index, !vnode.attrs.entry.starred);
                  raf.scheduleFullRedraw();
                },
              },
              m(Icon, {icon: STAR, filled: vnode.attrs.entry.starred}),
              ),
          m('button',
            {
              onclick: () => vnode.attrs.runQuery(query),
            },
            m(Icon, {icon: 'play_arrow'})),
          m('button',
            {
              onclick: () => {
                queryHistoryStorage.remove(vnode.attrs.index);
                raf.scheduleFullRedraw();
              },
            },
            m(Icon, {icon: 'delete'}))),
        m('pre', query));
  }
}

class HistoryStorage {
  data: QueryHistory;
  maxItems = 50;

  constructor() {
    this.data = this.load();
  }

  saveQuery(query: string) {
    const items = this.data;
    let firstUnstarred = -1;
    let countUnstarred = 0;
    for (let i = 0; i < items.length; i++) {
      if (!items[i].starred) {
        countUnstarred++;
        if (firstUnstarred === -1) {
          firstUnstarred = i;
        }
      }

      if (items[i].query === query) {
        // Query is already in the history, no need to save
        return;
      }
    }

    if (countUnstarred >= this.maxItems) {
      assertTrue(firstUnstarred !== -1);
      items.splice(firstUnstarred, 1);
    }

    items.push({query, starred: false});
    this.save();
  }

  setStarred(index: number, starred: boolean) {
    assertTrue(index >= 0 && index < this.data.length);
    this.data[index].starred = starred;
    this.save();
  }

  remove(index: number) {
    assertTrue(index >= 0 && index < this.data.length);
    this.data.splice(index, 1);
    this.save();
  }

  private load(): QueryHistory {
    const value = window.localStorage.getItem(QUERY_HISTORY_KEY);
    if (value === null) {
      return [];
    }

    return runValidator(queryHistoryValidator, JSON.parse(value)).result;
  }

  private save() {
    window.localStorage.setItem(QUERY_HISTORY_KEY, JSON.stringify(this.data));
  }
}

const queryHistoryEntryValidator = record({query: str(), starred: bool()});

type QueryHistoryEntry = ValidatedType<typeof queryHistoryEntryValidator>;

const queryHistoryValidator = arrayOf(queryHistoryEntryValidator);

type QueryHistory = ValidatedType<typeof queryHistoryValidator>;

export const queryHistoryStorage = new HistoryStorage();
