/**
 * @license
 * Copyright (C) 2017 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-autogrow-textarea/iron-autogrow-textarea';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-select/gr-select';
import {encodeURL, getBaseUrl} from '../../../utils/url-util';
import {AccessPermissionId} from '../../../utils/access-util';
import {fireEvent} from '../../../utils/event-util';
import {formStyles} from '../../../styles/gr-form-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {LitElement, PropertyValues, html, css} from 'lit';
import {customElement, property, state} from 'lit/decorators';
import {BindValueChangeEvent} from '../../../types/events';
import {ifDefined} from 'lit/directives/if-defined';
import {EditablePermissionRuleInfo} from '../gr-repo-access/gr-repo-access-interfaces';
import {PermissionAction} from '../../../constants/constants';

/**
 * Fired when the rule has been modified or removed.
 *
 * @event access-modified
 */

/**
 * Fired when a rule that was previously added was removed.
 *
 * @event added-rule-removed
 */

const PRIORITY_OPTIONS = [PermissionAction.BATCH, PermissionAction.INTERACTIVE];

const Action = {
  ALLOW: PermissionAction.ALLOW,
  DENY: PermissionAction.DENY,
  BLOCK: PermissionAction.BLOCK,
};

const DROPDOWN_OPTIONS = [
  PermissionAction.ALLOW,
  PermissionAction.DENY,
  PermissionAction.BLOCK,
];

const ForcePushOptions = {
  ALLOW: [
    {name: 'Allow pushing (but not force pushing)', value: false},
    {name: 'Allow pushing with or without force', value: true},
  ],
  BLOCK: [
    {name: 'Block pushing with or without force', value: false},
    {name: 'Block force pushing', value: true},
  ],
};

const FORCE_EDIT_OPTIONS = [
  {
    name: 'No Force Edit',
    value: false,
  },
  {
    name: 'Force Edit',
    value: true,
  },
];

type Rule = {value?: EditablePermissionRuleInfo};

interface RuleLabel {
  values: RuleLabelValue[];
}

interface RuleLabelValue {
  value: number;
  text: string;
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-rule-editor': GrRuleEditor;
  }
}

@customElement('gr-rule-editor')
export class GrRuleEditor extends LitElement {
  @property({type: Boolean})
  hasRange?: boolean;

  @property({type: Object})
  label?: RuleLabel;

  @property({type: Boolean})
  editing = false;

  @property({type: String})
  groupId?: string;

  @property({type: String})
  groupName?: string;

  // This is required value for this component
  @property({type: String})
  permission!: AccessPermissionId;

  @property({type: Object})
  rule?: Rule;

  @property({type: String})
  section?: string;

  // private but used in test
  @state() deleted = false;

  // private but used in test
  @state() originalRuleValues?: EditablePermissionRuleInfo;

  constructor() {
    super();
    this.addEventListener('access-saved', () => this.handleAccessSaved());
  }

  override connectedCallback() {
    super.connectedCallback();
    if (this.rule) {
      this.setupValues();
    }
    // Check needed for test purposes.
    if (!this.originalRuleValues && this.rule) {
      this.setOriginalRuleValues();
    }
  }

  static override get styles() {
    return [
      formStyles,
      sharedStyles,
      css`
        :host {
          border-bottom: 1px solid var(--border-color);
          padding: var(--spacing-m);
          display: block;
        }
        #removeBtn {
          display: none;
        }
        .editing #removeBtn {
          display: flex;
        }
        #options {
          align-items: baseline;
          display: flex;
        }
        #options > * {
          margin-right: var(--spacing-m);
        }
        #mainContainer {
          align-items: baseline;
          display: flex;
          flex-wrap: nowrap;
          justify-content: space-between;
        }
        #deletedContainer.deleted {
          align-items: baseline;
          display: flex;
          justify-content: space-between;
        }
        #undoBtn,
        #force,
        #deletedContainer,
        #mainContainer.deleted {
          display: none;
        }
        #undoBtn.modified,
        #force.force {
          display: block;
        }
        .groupPath {
          color: var(--deemphasized-text-color);
        }
        iron-autogrow-textarea {
          width: 14em;
        }
      `,
    ];
  }

  override render() {
    return html`
      <div
        id="mainContainer"
        class="gr-form-styles ${this.computeSectionClass()}"
      >
        <div id="options">
          <gr-select
            id="action"
            .bindValue=${this.rule?.value?.action}
            @bind-value-changed=${(e: BindValueChangeEvent) => {
              this.handleActionBindValueChanged(e);
            }}
          >
            <select ?disabled=${!this.editing}>
              ${this.computeOptions().map(
                item => html` <option value=${item}>${item}</option> `
              )}
            </select>
          </gr-select>
          ${this.renderMinAndMaxLabel()} ${this.renderMinAndMaxInput()}
          <a
            class="groupPath"
            href="${ifDefined(this.computeGroupPath(this.groupId))}"
          >
            ${this.groupName}
          </a>
          <gr-select
            id="force"
            class="${this.computeForce(this.rule?.value?.action)
              ? 'force'
              : ''}"
            .bindValue=${this.rule?.value?.force}
            @bind-value-changed=${(e: BindValueChangeEvent) => {
              this.handleForceBindValueChanged(e);
            }}
          >
            <select ?disabled=${!this.editing}>
              ${this.computeForceOptions(this.rule?.value?.action).map(
                item => html`
                  <option value=${item.value}>${item.name}</option>
                `
              )}
            </select>
          </gr-select>
        </div>
        <gr-button
          link
          id="removeBtn"
          @click=${() => {
            this.handleRemoveRule();
          }}
          >Remove</gr-button
        >
      </div>
      <div
        id="deletedContainer"
        class="gr-form-styles ${this.computeSectionClass()}"
      >
        ${this.groupName} was deleted
        <gr-button
          link
          id="undoRemoveBtn"
          @click=${() => {
            this.handleUndoRemove();
          }}
          >Undo</gr-button
        >
      </div>
    `;
  }

  private renderMinAndMaxLabel() {
    if (!this.label) return;

    return html`
      <gr-select
        id="labelMin"
        .bindValue=${this.rule?.value?.min}
        @bind-value-changed=${(e: BindValueChangeEvent) => {
          this.handleMinBindValueChanged(e);
        }}
      >
        <select ?disabled=${!this.editing}>
          ${this.label.values.map(
            item => html` <option value=${item.value}>${item.value}</option> `
          )}
        </select>
      </gr-select>
      <gr-select
        id="labelMax"
        .bindValue=${this.rule?.value?.max}
        @bind-value-changed=${(e: BindValueChangeEvent) => {
          this.handleMaxBindValueChanged(e);
        }}
      >
        <select ?disabled=${!this.editing}>
          ${this.label.values.map(
            item => html` <option value=${item.value}>${item.value}</option> `
          )}
        </select>
      </gr-select>
    `;
  }

  private renderMinAndMaxInput() {
    if (!this.hasRange) return;

    return html`
      <iron-autogrow-textarea
        id="minInput"
        class="min"
        autocomplete="on"
        placeholder="Min value"
        .bindValue=${this.rule?.value?.min}
        ?disabled=${!this.editing}
        @bind-value-changed=${(e: BindValueChangeEvent) => {
          this.handleMinBindValueChanged(e);
        }}
      ></iron-autogrow-textarea>
      <iron-autogrow-textarea
        id="maxInput"
        class="max"
        autocomplete="on"
        placeholder="Max value"
        .bindValue=${this.rule?.value?.max}
        ?disabled=${!this.editing}
        @bind-value-changed=${(e: BindValueChangeEvent) => {
          this.handleMaxBindValueChanged(e);
        }}
      ></iron-autogrow-textarea>
    `;
  }

  override willUpdate(changedProperties: PropertyValues) {
    if (changedProperties.has('editing')) {
      this.handleEditingChanged(changedProperties.get('editing') as boolean);
    }
  }

  // private but used in test
  setupValues() {
    if (!this.rule?.value) {
      this.setDefaultRuleValues();
    }
  }

  // private but used in test
  computeForce(action?: string) {
    if (AccessPermissionId.PUSH === this.permission && action !== Action.DENY) {
      return true;
    }

    return AccessPermissionId.EDIT_TOPIC_NAME === this.permission;
  }

  // private but used in test
  computeGroupPath(groupId?: string) {
    if (!groupId) return;
    return `${getBaseUrl()}/admin/groups/${encodeURL(groupId, true)}`;
  }

  // private but used in test
  handleAccessSaved() {
    // Set a new 'original' value to keep track of after the value has been
    // saved.
    this.setOriginalRuleValues();
  }

  private handleEditingChanged(editingOld: boolean) {
    // Ignore when editing gets set initially.
    if (!editingOld) {
      return;
    }
    // Restore original values if no longer editing.
    if (!this.editing) {
      this.handleUndoChange();
    }
  }

  // private but used in test
  computeSectionClass() {
    const classList = [];
    if (this.editing) {
      classList.push('editing');
    }
    if (this.deleted) {
      classList.push('deleted');
    }
    return classList.join(' ');
  }

  // private but used in test
  computeForceOptions(action?: string) {
    if (this.permission === AccessPermissionId.PUSH) {
      if (action === Action.ALLOW) {
        return ForcePushOptions.ALLOW;
      } else if (action === Action.BLOCK) {
        return ForcePushOptions.BLOCK;
      } else {
        return [];
      }
    } else if (this.permission === AccessPermissionId.EDIT_TOPIC_NAME) {
      return FORCE_EDIT_OPTIONS;
    }
    return [];
  }

  // private but used in test
  getDefaultRuleValues(): EditablePermissionRuleInfo {
    if (this.permission === AccessPermissionId.PRIORITY) {
      return {action: PRIORITY_OPTIONS[0]};
    }
    if (this.label) {
      return {
        action: DROPDOWN_OPTIONS[0],
        min: this.label.values[0].value,
        max: this.label.values[this.label.values.length - 1].value,
      };
    }
    if (this.computeForce(Action.ALLOW)) {
      return {
        action: DROPDOWN_OPTIONS[0],
        force: this.computeForceOptions(Action.ALLOW)[0].value,
      };
    }
    return {action: DROPDOWN_OPTIONS[0]};
  }

  // private but used in test
  setDefaultRuleValues() {
    this.rule!.value = this.getDefaultRuleValues();

    this.handleRuleChange();
  }

  // private but used in test
  computeOptions() {
    if (this.permission === 'priority') {
      return PRIORITY_OPTIONS;
    }
    return DROPDOWN_OPTIONS;
  }

  private handleRemoveRule() {
    if (!this.rule?.value) return;
    if (this.rule.value.added) {
      fireEvent(this, 'added-rule-removed');
    }
    this.deleted = true;
    this.rule.value.deleted = true;

    this.handleRuleChange();

    fireEvent(this, 'access-modified');
  }

  private handleUndoRemove() {
    if (!this.rule?.value) return;
    this.deleted = false;
    delete this.rule.value.deleted;

    this.handleRuleChange();
  }

  private handleUndoChange() {
    if (!this.originalRuleValues || !this.rule?.value) {
      return;
    }
    // gr-permission will take care of removing rules that were added but
    // unsaved. We need to keep the added bit for the filter.
    if (this.rule.value.added) {
      return;
    }
    this.rule.value = {...this.originalRuleValues};
    this.deleted = false;
    delete this.rule.value.deleted;
    delete this.rule.value.modified;

    this.handleRuleChange();
  }

  // private but used in test
  handleValueChange() {
    if (!this.originalRuleValues || !this.rule?.value) {
      return;
    }
    this.rule.value.modified = true;

    this.handleRuleChange();

    // Allows overall access page to know a change has been made.
    fireEvent(this, 'access-modified');
  }

  // private but used in test
  setOriginalRuleValues() {
    if (!this.rule?.value) return;
    this.originalRuleValues = {...this.rule.value};
  }

  private handleActionBindValueChanged(e: BindValueChangeEvent) {
    if (
      !this.rule?.value ||
      e.detail.value === undefined ||
      this.rule.value.action === String(e.detail.value)
    )
      return;

    this.rule.value.action = String(e.detail.value) as PermissionAction;

    this.handleValueChange();
  }

  private handleMinBindValueChanged(e: BindValueChangeEvent) {
    if (
      !this.rule?.value ||
      e.detail.value === undefined ||
      this.rule.value.min === Number(e.detail.value)
    )
      return;
    this.rule.value.min = Number(e.detail.value);

    this.handleValueChange();
  }

  private handleMaxBindValueChanged(e: BindValueChangeEvent) {
    if (
      !this.rule?.value ||
      e.detail.value === undefined ||
      this.rule.value.max === Number(e.detail.value)
    )
      return;
    this.rule.value.max = Number(e.detail.value);

    this.handleValueChange();
  }

  private handleForceBindValueChanged(e: BindValueChangeEvent) {
    const forceValue = String(e.detail.value) === 'true' ? true : false;
    if (
      !this.rule?.value ||
      e.detail.value === undefined ||
      this.rule.value.force === forceValue
    )
      return;
    this.rule.value.force = forceValue;

    this.handleValueChange();
  }

  private handleRuleChange() {
    this.requestUpdate('rule');

    this.dispatchEvent(
      new CustomEvent('rule-changed', {
        detail: {value: this.rule},
        composed: true,
        bubbles: true,
      })
    );
  }
}
