// 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 {Icons} from '../base/semantic_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;
  setQuery: (query: string) => void;
}

export class QueryHistoryComponent
  implements m.ClassComponent<QueryHistoryComponentAttrs>
{
  view({attrs}: m.CVnode<QueryHistoryComponentAttrs>): m.Child {
    const runQuery = attrs.runQuery;
    const setQuery = attrs.setQuery;
    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, setQuery});
    }
    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;
  setQuery: (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: Icons.Star, filled: vnode.attrs.entry.starred}),
        ),
        m(
          'button',
          {
            onclick: () => vnode.attrs.setQuery(query),
          },
          m(Icon, {icon: 'edit'}),
        ),
        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();
