// Copyright (C) 2020 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 {channelChanged, getNextChannel, setChannel} from '../common/channels';
import {featureFlags, Flag, OverrideState} from '../core/feature_flags';
import {raf} from '../core/raf_scheduler';

import {createPage} from './pages';

const RELEASE_PROCESS_URL =
    'https://perfetto.dev/docs/visualization/perfetto-ui-release-process';

interface FlagOption {
  id: string;
  name: string;
}

interface SelectWidgetAttrs {
  label: string;
  description: m.Children;
  options: FlagOption[];
  selected: string;
  onSelect: (id: string) => void;
}

class SelectWidget implements m.ClassComponent<SelectWidgetAttrs> {
  view(vnode: m.Vnode<SelectWidgetAttrs>) {
    const attrs = vnode.attrs;
    return m(
        '.flag-widget',
        m('label', attrs.label),
        m(
            'select',
            {
              onchange: (e: InputEvent) => {
                const value = (e.target as HTMLSelectElement).value;
                attrs.onSelect(value);
                raf.scheduleFullRedraw();
              },
            },
            attrs.options.map((o) => {
              const selected = o.id === attrs.selected;
              return m('option', {value: o.id, selected}, o.name);
            }),
            ),
        m('.description', attrs.description),
    );
  }
}

interface FlagWidgetAttrs {
  flag: Flag;
}

class FlagWidget implements m.ClassComponent<FlagWidgetAttrs> {
  view(vnode: m.Vnode<FlagWidgetAttrs>) {
    const flag = vnode.attrs.flag;
    const defaultState = flag.defaultValue ? 'Enabled' : 'Disabled';
    return m(SelectWidget, {
      label: flag.name,
      description: flag.description,
      options: [
        {id: OverrideState.DEFAULT, name: `Default (${defaultState})`},
        {id: OverrideState.TRUE, name: 'Enabled'},
        {id: OverrideState.FALSE, name: 'Disabled'},
      ],
      selected: flag.overriddenState(),
      onSelect: (value: string) => {
        switch (value) {
          case OverrideState.TRUE:
            flag.set(true);
            break;
          case OverrideState.FALSE:
            flag.set(false);
            break;
          default:
          case OverrideState.DEFAULT:
            flag.reset();
            break;
        }
      },
    });
  }
}

export const FlagsPage = createPage({
  view() {
    const needsReload = channelChanged();
    return m(
        '.flags-page',
        m(
            '.flags-content',
            m('h1', 'Feature flags'),
            needsReload &&
                [
                  m('h2', 'Please reload for your changes to take effect'),
                ],
            m(SelectWidget, {
              label: 'Release channel',
              description: [
                'Which release channel of the UI to use. See ',
                m('a',
                  {
                    href: RELEASE_PROCESS_URL,
                  },
                  'Release Process'),
                ' for more information.',
              ],
              options: [
                {id: 'stable', name: 'Stable (default)'},
                {id: 'canary', name: 'Canary'},
                {id: 'autopush', name: 'Autopush'},
              ],
              selected: getNextChannel(),
              onSelect: (id) => setChannel(id),
            }),
            m('button',
              {
                onclick: () => {
                  featureFlags.resetAll();
                  raf.scheduleFullRedraw();
                },
              },
              'Reset all below'),

            featureFlags.allFlags().map((flag) => m(FlagWidget, {flag})),
            ));
  },
});
