// Copyright (C) 2021 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.

// This file should not import anything else. Since the flags will be used from
// ~everywhere and the are "statically" initialized (i.e. files construct Flags
// at import time) if this file starts importing anything we will quickly run
// into issues with initialization order which will be a pain.

interface FlagSettings {
  id: string;
  defaultValue: boolean;
  description: string;
  name?: string;
  devOnly?: boolean;
}

export enum OverrideState {
  DEFAULT = 'DEFAULT',
  TRUE = 'OVERRIDE_TRUE',
  FALSE = 'OVERRIDE_FALSE',
}

export interface FlagStore {
  load(): object;
  save(o: object): void;
}

// Stored state for a number of flags.
interface FlagOverrides {
  [id: string]: OverrideState;
}

// Check if the given object is a valid FlagOverrides.
// This is necessary since someone could modify the persisted flags
// behind our backs.
function isFlagOverrides(o: object): o is FlagOverrides {
  const states =
      [OverrideState.TRUE.toString(), OverrideState.FALSE.toString()];
  for (const v of Object.values(o)) {
    if (typeof v !== 'string' || !states.includes(v)) {
      return false;
    }
  }
  return true;
}

class Flags {
  private store: FlagStore;
  private flags: Map<string, FlagImpl>;
  private overrides: FlagOverrides;

  constructor(store: FlagStore) {
    this.store = store;
    this.flags = new Map();
    this.overrides = {};
    this.load();
  }

  register(settings: FlagSettings): Flag {
    const id = settings.id;
    if (this.flags.has(id)) {
      throw new Error(`Flag with id "${id}" is already registered.`);
    }

    const saved = this.overrides[id];
    const state = saved === undefined ? OverrideState.DEFAULT : saved;
    const flag = new FlagImpl(this, state, settings);
    this.flags.set(id, flag);
    return flag;
  }

  allFlags(): Flag[] {
    const includeDevFlags =
        ['127.0.0.1', '::1', 'localhost'].includes(window.location.hostname);

    let flags = [...this.flags.values()];
    flags = flags.filter((flag) => includeDevFlags || !flag.devOnly);
    flags.sort((a, b) => a.name.localeCompare(b.name));
    return flags;
  }

  resetAll() {
    for (const flag of this.flags.values()) {
      flag.state = OverrideState.DEFAULT;
    }
    this.save();
  }

  load(): void {
    const o = this.store.load();
    if (isFlagOverrides(o)) {
      this.overrides = o;
    }
  }

  save(): void {
    for (const flag of this.flags.values()) {
      if (flag.isOverridden()) {
        this.overrides[flag.id] = flag.state;
      } else {
        delete this.overrides[flag.id];
      }
    }

    this.store.save(this.overrides);
  }
}

export interface Flag {
  // A unique identifier for this flag ("magicSorting")
  readonly id: string;

  // The name of the flag the user sees ("New track sorting algorithm")
  readonly name: string;

  // A longer description which is displayed to the user.
  // "Sort tracks using an embedded tfLite model based on your expression
  // while waiting for the trace to load."
  readonly description: string;

  // Whether the flag defaults to true or false.
  // If !flag.isOverridden() then flag.get() === flag.defaultValue
  readonly defaultValue: boolean;

  // Get the current value of the flag.
  get(): boolean;

  // Override the flag and persist the new value.
  set(value: boolean): void;

  // If the flag has been overridden.
  // Note: A flag can be overridden to its default value.
  isOverridden(): boolean;

  // Reset the flag to its default setting.
  reset(): void;

  // Get the current state of the flag.
  overriddenState(): OverrideState;
}

class FlagImpl implements Flag {
  registry: Flags;
  state: OverrideState;

  readonly id: string;
  readonly name: string;
  readonly description: string;
  readonly defaultValue: boolean;
  readonly devOnly: boolean;

  constructor(registry: Flags, state: OverrideState, settings: FlagSettings) {
    this.registry = registry;
    this.id = settings.id;
    this.state = state;
    this.description = settings.description;
    this.defaultValue = settings.defaultValue;
    this.name = settings.name || settings.id;
    this.devOnly = settings.devOnly || false;
  }

  get(): boolean {
    switch (this.state) {
      case OverrideState.TRUE:
        return true;
      case OverrideState.FALSE:
        return false;
      case OverrideState.DEFAULT:
      default:
        return this.defaultValue;
    }
  }

  set(value: boolean): void {
    const next = value ? OverrideState.TRUE : OverrideState.FALSE;
    if (this.state === next) {
      return;
    }
    this.state = next;
    this.registry.save();
  }

  overriddenState(): OverrideState {
    return this.state;
  }

  reset() {
    this.state = OverrideState.DEFAULT;
    this.registry.save();
  }

  isOverridden(): boolean {
    return this.state !== OverrideState.DEFAULT;
  }
}

class LocalStorageStore implements FlagStore {
  static KEY = 'perfettoFeatureFlags';

  load(): object {
    const s = localStorage.getItem(LocalStorageStore.KEY);
    let parsed: object;
    try {
      parsed = JSON.parse(s || '{}');
    } catch (e) {
      return {};
    }
    if (typeof parsed !== 'object' || parsed === null) {
      return {};
    }
    return parsed;
  }

  save(o: object): void {
    const s = JSON.stringify(o);
    localStorage.setItem(LocalStorageStore.KEY, s);
  }
}

export const FlagsForTesting = Flags;
export const featureFlags = new Flags(new LocalStorageStore());

export const PERF_SAMPLE_FLAG = featureFlags.register({
  id: 'perfSampleFlamegraph',
  name: 'Perf Sample Flamegraph',
  description: 'Show flamegraph generated by a perf sample.',
  defaultValue: true,
});

export const RECORDING_V2_FLAG = featureFlags.register({
  id: 'recordingv2',
  name: 'Recording V2',
  description: 'Record using V2 interface',
  defaultValue: false,
});
