// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';
import 'package:angular_components/content/deferred_content.dart';
import 'package:angular_forms/angular_forms.dart' show formDirectives;
import 'package:angular_components/laminate/enums/alignment.dart';
import 'package:angular_components/material_checkbox/material_checkbox.dart';
import 'package:angular_components/material_chips/material_chips.dart';
import 'package:angular_components/material_chips/material_chip.dart';
import 'package:angular_components/material_radio/material_radio.dart';
import 'package:angular_components/material_tooltip/material_tooltip.dart';
import 'package:angular_components/material_tooltip/module.dart' as tooltip;

import 'log_component.dart';

import 'commit.dart';

@Component(
    selector: 'results-selector-panel',
    directives: [
      coreDirectives,
      formDirectives,
      DeferredContentDirective,
      LogComponent,
      MaterialButtonComponent,
      MaterialCheckboxComponent,
      MaterialChipComponent,
      MaterialChipsComponent,
      MaterialPaperTooltipComponent,
      MaterialRadioComponent,
      MaterialRadioGroupComponent,
      MaterialTooltipDirective,
      MaterialTooltipTargetDirective,
      RelativePosition
    ],
    providers: [popupBindings, tooltip.materialTooltipBindings],
    templateUrl: 'results_selector_panel.html',
    styleUrls: ([
      'commit_component.css',
      'package:angular_components/css/mdc_web/card/mdc-card.scss.css'
    ]))
class ResultsSelectorPanel {
  ResultsSelectorPanel();

  @Input()
  set changes(Changes changes) {
    _changes = changes;
    selectableChanges = [
      for (ConfigGroup c in changes) SelectableConfigurationGroup(c, this)
    ];
    initializeSelected();
  }

  @Input()
  ChangeGroup commit;

  @Input()
  set selected(Set<Change> selected) {
    _selected = selected;
    initializeSelected();
  }

  Changes _changes;
  Set<Change> _selected;
  List<SelectableConfigurationGroup> selectableChanges;
  int resultLimit = 10;

  Changes get changes => _changes;

  final preferredTooltipPositions = [
    RelativePosition.OffsetBottomLeft,
    RelativePosition.OffsetTopLeft
  ];

  void initializeSelected() {
    if (_selected != null && _changes != null) {
      _selected.addAll([
        for (final c in selectableChanges)
          for (SelectableResultGroup r in c.resultGroups)
            for (SelectableChange h in r.changes) h.change
      ]);
    }
  }
}

class SelectableChange {
  final Change change;
  bool selected = true;
  final SelectableResultGroup resultGroup;
  final SelectableConfigurationGroup configurationGroup;
  final ResultsSelectorPanel panel;

  SelectableChange(
      this.change, this.resultGroup, this.configurationGroup, this.panel);

  void onChange(bool event) {
    if (selected == event) return;
    selected = event;
    if (event) {
      panel._selected.add(this.change);
    } else {
      panel._selected.remove(this.change);
    }
    resultGroup.checkbox.setMixed();
    configurationGroup.checkbox.setMixed();
  }
}

class SelectableResultGroup {
  List<SelectableChange> changes;
  SelectableConfigurationGroup configurationGroup;
  FixedMixedCheckbox checkbox = FixedMixedCheckbox();

  SelectableResultGroup(
      ResultGroup group, this.configurationGroup, ResultsSelectorPanel panel) {
    changes = [
      for (final change in group)
        SelectableChange(change, this, configurationGroup, panel)
    ];
  }

  void onChange(String event) {
    if (checkbox.eventMatchesState(event)) return;
    assert(event != 'mixed');
    bool newChecked = event == 'true';
    checkbox.setState(newChecked, false);
    for (final change in changes) {
      change.selected = newChecked;
    }
    configurationGroup.checkbox.setMixed();
  }
}

class SelectableConfigurationGroup {
  List<SelectableResultGroup> resultGroups;
  FixedMixedCheckbox checkbox = FixedMixedCheckbox();

  SelectableConfigurationGroup(
      ConfigGroup configGroup, ResultsSelectorPanel panel) {
    resultGroups = [
      for (final resultGroup in configGroup)
        SelectableResultGroup(resultGroup, this, panel)
    ];
  }

  get summaries =>
      resultGroups.first.changes.first.change.configurations.summaries;

  void onChange(String event) {
    if (checkbox.eventMatchesState(event)) return;
    assert(event != 'mixed');
    bool newChecked = event == 'true';
    checkbox.setState(newChecked, false);
    for (final group in resultGroups) {
      group.checkbox.setState(newChecked, false);
      for (final change in group.changes) {
        change.selected = newChecked;
      }
    }
  }
}

class FixedMixedCheckbox {
  bool checked = true;
  bool indeterminate = false;
  // Model change indeterminate <-> checked generates a bad 'unchecked' event.
  // Workaround for issue https://github.com/dart-lang/angular_components/issues/434
  bool expectBadEvent = false;

  bool eventMatchesState(String event) {
    if (event == 'mixed' && indeterminate ||
        event == 'true' && checked ||
        event == 'false' && !indeterminate && !checked ||
        event == 'false' && expectBadEvent) {
      expectBadEvent = false;
      return true;
    }
    return false;
  }

  void setState(bool newChecked, bool newIndeterminate) {
    assert(!newChecked || !newIndeterminate);
    if (newChecked && indeterminate || checked && newIndeterminate) {
      expectBadEvent = true;
    }
    checked = newChecked;
    indeterminate = newIndeterminate;
  }

  void setMixed() => setState(false, true);
}
