/**
 * @license
 * Copyright (C) 2016 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 '@polymer/iron-input/iron-input';
import '../../shared/gr-autocomplete/gr-autocomplete';
import '../../shared/gr-button/gr-button';
import '../../../styles/gr-form-styles';
import '../../../styles/shared-styles';
import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-watched-projects-editor_html';
import {customElement, property} from '@polymer/decorators';
import {
  AutocompleteQuery,
  GrAutocomplete,
  AutocompleteSuggestion,
} from '../../shared/gr-autocomplete/gr-autocomplete';
import {hasOwnProperty} from '../../../utils/common-util';
import {ProjectWatchInfo} from '../../../types/common';
import {appContext} from '../../../services/app-context';
import {IronInputElement} from '@polymer/iron-input';

const NOTIFICATION_TYPES = [
  {name: 'Changes', key: 'notify_new_changes'},
  {name: 'Patches', key: 'notify_new_patch_sets'},
  {name: 'Comments', key: 'notify_all_comments'},
  {name: 'Submits', key: 'notify_submitted_changes'},
  {name: 'Abandons', key: 'notify_abandoned_changes'},
];

export interface GrWatchedProjectsEditor {
  $: {
    newFilter: HTMLInputElement;
    newFilterInput: IronInputElement;
    newProject: GrAutocomplete;
  };
}

@customElement('gr-watched-projects-editor')
export class GrWatchedProjectsEditor extends PolymerElement {
  static get template() {
    return htmlTemplate;
  }

  @property({type: Boolean, notify: true})
  hasUnsavedChanges = false;

  @property({type: Array})
  _projects?: ProjectWatchInfo[];

  @property({type: Array})
  _projectsToRemove: ProjectWatchInfo[] = [];

  @property({type: Object})
  _query: AutocompleteQuery;

  private readonly restApiService = appContext.restApiService;

  constructor() {
    super();
    this._query = input => this._getProjectSuggestions(input);
  }

  loadData() {
    return this.restApiService.getWatchedProjects().then(projs => {
      this._projects = projs;
    });
  }

  save() {
    let deletePromise: Promise<Response | undefined>;
    if (this._projectsToRemove.length) {
      deletePromise = this.restApiService.deleteWatchedProjects(
        this._projectsToRemove
      );
    } else {
      deletePromise = Promise.resolve(undefined);
    }

    return deletePromise
      .then(() => {
        if (this._projects) {
          return this.restApiService.saveWatchedProjects(this._projects);
        } else {
          return Promise.resolve(undefined);
        }
      })
      .then(projects => {
        this._projects = projects;
        this._projectsToRemove = [];
        this.hasUnsavedChanges = false;
      });
  }

  _getTypes() {
    return NOTIFICATION_TYPES;
  }

  _getTypeCount() {
    return this._getTypes().length;
  }

  _computeCheckboxChecked(project: ProjectWatchInfo, key: string) {
    return hasOwnProperty(project, key);
  }

  _getProjectSuggestions(input: string) {
    return this.restApiService.getSuggestedProjects(input).then(response => {
      const projects: AutocompleteSuggestion[] = [];
      for (const [name, project] of Object.entries(response ?? {})) {
        projects.push({name, value: project.id});
      }
      return projects;
    });
  }

  _handleRemoveProject(e: Event) {
    const el = (dom(e) as EventApi).localTarget as HTMLInputElement;
    const dataIndex = el.getAttribute('data-index');
    if (dataIndex === null || !this._projects) return;
    const index = Number(dataIndex);
    const project = this._projects[index];
    this.splice('_projects', index, 1);
    this.push('_projectsToRemove', project);
    this.hasUnsavedChanges = true;
  }

  _canAddProject(
    project: string | null,
    text: string | null,
    filter: string | null
  ) {
    if (project === null && text === null) {
      return false;
    }

    // This will only be used if not using the auto complete
    if (!project && text) {
      return true;
    }

    if (!this._projects) return true;
    // Check if the project with filter is already in the list.
    for (let i = 0; i < this._projects.length; i++) {
      if (
        this._projects[i].project === project &&
        this.areFiltersEqual(this._projects[i].filter, filter)
      ) {
        return false;
      }
    }

    return true;
  }

  _getNewProjectIndex(name: string, filter: string | null) {
    if (!this._projects) return;
    let i;
    for (i = 0; i < this._projects.length; i++) {
      const projectFilter = this._projects[i].filter;
      if (
        this._projects[i].project > name ||
        (this._projects[i].project === name &&
          this.isFilterDefined(projectFilter) &&
          this.isFilterDefined(filter) &&
          projectFilter! > filter!)
      ) {
        break;
      }
    }
    return i;
  }

  _handleAddProject() {
    const newProject = this.$.newProject.value;
    const newProjectName = this.$.newProject.text;
    const filter = this.$.newFilter.value || null;

    if (!this._canAddProject(newProject, newProjectName, filter)) {
      return;
    }

    const insertIndex = this._getNewProjectIndex(newProjectName, filter);

    if (insertIndex !== undefined) {
      this.splice('_projects', insertIndex, 0, {
        project: newProjectName,
        filter,
        _is_local: true,
      });
    }

    this.$.newProject.clear();
    this.$.newFilter.value = '';
    this.hasUnsavedChanges = true;
  }

  _handleCheckboxChange(e: Event) {
    const el = (dom(e) as EventApi).localTarget as HTMLInputElement;
    if (el === null) return;
    const dataIndex = el.getAttribute('data-index');
    const key = el.getAttribute('data-key');
    if (dataIndex === null || key === null) return;
    const index = Number(dataIndex);
    const checked = el.checked;
    this.set(['_projects', index, key], !!checked);
    this.hasUnsavedChanges = true;
  }

  _handleNotifCellClick(e: Event) {
    if (e.target === null) return;
    const checkbox = (e.target as HTMLElement).querySelector('input');
    if (checkbox) {
      checkbox.click();
    }
  }

  isFilterDefined(filter: string | null | undefined) {
    return filter !== null && filter !== undefined;
  }

  areFiltersEqual(
    filter1: string | null | undefined,
    filter2: string | null | undefined
  ) {
    // null and undefined are equal
    if (!this.isFilterDefined(filter1) && !this.isFilterDefined(filter2)) {
      return true;
    }
    return filter1 === filter2;
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-watched-projects-editor': GrWatchedProjectsEditor;
  }
}
