/**
 * @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-input/iron-input';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
import '../../plugins/gr-endpoint-param/gr-endpoint-param';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-download-commands/gr-download-commands';
import '../../shared/gr-select/gr-select';
import '../../shared/gr-textarea/gr-textarea';
import '../gr-repo-plugin-config/gr-repo-plugin-config';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {
  ConfigInfo,
  RepoName,
  InheritedBooleanInfo,
  SchemesInfoMap,
  ConfigInput,
  MaxObjectSizeLimitInfo,
  PluginParameterToConfigParameterInfoMap,
} from '../../../types/common';
import {
  InheritedBooleanInfoConfiguredValue,
  ProjectState,
  SubmitType,
} from '../../../constants/constants';
import {hasOwnProperty} from '../../../utils/common-util';
import {firePageError, fireTitleChange} from '../../../utils/event-util';
import {getAppContext} from '../../../services/app-context';
import {WebLinkInfo} from '../../../types/diff';
import {ErrorCallback} from '../../../api/rest';
import {fontStyles} from '../../../styles/gr-font-styles';
import {formStyles} from '../../../styles/gr-form-styles';
import {subpageStyles} from '../../../styles/gr-subpage-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {BindValueChangeEvent} from '../../../types/events';
import {deepClone} from '../../../utils/deep-util';
import {LitElement, PropertyValues, css, html} from 'lit';
import {customElement, property, state} from 'lit/decorators';
import {subscribe} from '../../lit/subscription-controller';

const STATES = {
  active: {value: ProjectState.ACTIVE, label: 'Active'},
  readOnly: {value: ProjectState.READ_ONLY, label: 'Read Only'},
  hidden: {value: ProjectState.HIDDEN, label: 'Hidden'},
};

const SUBMIT_TYPES = {
  // Exclude INHERIT, which is handled specially.
  mergeIfNecessary: {
    value: 'MERGE_IF_NECESSARY',
    label: 'Merge if necessary',
  },
  fastForwardOnly: {
    value: 'FAST_FORWARD_ONLY',
    label: 'Fast forward only',
  },
  rebaseAlways: {
    value: 'REBASE_ALWAYS',
    label: 'Rebase Always',
  },
  rebaseIfNecessary: {
    value: 'REBASE_IF_NECESSARY',
    label: 'Rebase if necessary',
  },
  mergeAlways: {
    value: 'MERGE_ALWAYS',
    label: 'Merge always',
  },
  cherryPick: {
    value: 'CHERRY_PICK',
    label: 'Cherry pick',
  },
};

declare global {
  interface HTMLElementTagNameMap {
    'gr-repo': GrRepo;
  }
}

@customElement('gr-repo')
export class GrRepo extends LitElement {
  private schemes: string[] = [];

  @property({type: String})
  repo?: RepoName;

  // private but used in test
  @state() loading = true;

  // private but used in test
  @state() repoConfig?: ConfigInfo;

  // private but used in test
  @state() readOnly = true;

  @state() private states = Object.values(STATES);

  @state() private originalConfig?: ConfigInfo;

  @state() private selectedScheme?: string;

  // private but used in test
  @state() schemesObj?: SchemesInfoMap;

  @state() private weblinks: WebLinkInfo[] = [];

  @state() private pluginConfigChanged = false;

  private readonly userModel = getAppContext().userModel;

  private readonly restApiService = getAppContext().restApiService;

  constructor() {
    super();
    subscribe(
      this,
      () => this.userModel.preferences$,
      prefs => {
        if (prefs?.download_scheme) {
          // Note (issue 5180): normalize the download scheme with lower-case.
          this.selectedScheme = prefs.download_scheme.toLowerCase();
        }
      }
    );
  }

  override connectedCallback() {
    super.connectedCallback();

    fireTitleChange(this, `${this.repo}`);
  }

  static override get styles() {
    return [
      fontStyles,
      formStyles,
      subpageStyles,
      sharedStyles,
      css`
        .info {
          margin-bottom: var(--spacing-xl);
        }
        h2.edited:after {
          color: var(--deemphasized-text-color);
          content: ' *';
        }
        .loading,
        .hide {
          display: none;
        }
        #loading.loading {
          display: block;
        }
        #loading:not(.loading) {
          display: none;
        }
        #options .repositorySettings {
          display: none;
        }
        #options .repositorySettings.showConfig {
          display: block;
        }
      `,
    ];
  }

  override render() {
    const configChanged = this.hasConfigChanged();
    return html`
      <div class="main gr-form-styles read-only">
        <div class="info">
          <h1 id="Title" class="heading-1">${this.repo}</h1>
          <hr />
          <div>
            <a href=${this.weblinks?.[0]?.url}
              ><gr-button link ?disabled=${!this.weblinks?.[0]?.url}
                >Browse</gr-button
              ></a
            ><a href=${this.computeChangesUrl(this.repo)}
              ><gr-button link>View Changes</gr-button></a
            >
          </div>
        </div>
        <div id="loading" class=${this.loading ? 'loading' : ''}>
          Loading...
        </div>
        <div id="loadedContent" class=${this.loading ? 'loading' : ''}>
          ${this.renderDownloadCommands()}
          <h2
            id="configurations"
            class="heading-2 ${configChanged ? 'edited' : ''}"
          >
            Configurations
          </h2>
          <div id="form">
            <fieldset>
              ${this.renderDescription()} ${this.renderRepoOptions()}
              ${this.renderPluginConfig()}
              <gr-button
                ?disabled=${this.readOnly || !configChanged}
                @click=${this.handleSaveRepoConfig}
                >Save changes</gr-button
              >
            </fieldset>
            <gr-endpoint-decorator name="repo-config">
              <gr-endpoint-param
                name="repoName"
                .value=${this.repo}
              ></gr-endpoint-param>
              <gr-endpoint-param
                name="readOnly"
                .value=${this.readOnly}
              ></gr-endpoint-param>
            </gr-endpoint-decorator>
          </div>
        </div>
      </div>
    `;
  }

  private renderDownloadCommands() {
    return html`
      <div
        id="downloadContent"
        class=${!this.schemes || !this.schemes.length ? 'hide' : ''}
      >
        <h2 id="download" class="heading-2">Download</h2>
        <fieldset>
          <gr-download-commands
            id="downloadCommands"
            .commands=${this.computeCommands(
              this.repo,
              this.schemesObj,
              this.selectedScheme
            )}
            .schemes=${this.schemes}
            .selectedScheme=${this.selectedScheme}
            @selected-scheme-changed=${(e: BindValueChangeEvent) => {
              if (this.loading) return;
              this.selectedScheme = e.detail.value;
            }}
          ></gr-download-commands>
        </fieldset>
      </div>
    `;
  }

  private renderDescription() {
    return html`
      <h3 id="Description" class="heading-3">Description</h3>
      <fieldset>
        <gr-textarea
          id="descriptionInput"
          class="description"
          autocomplete="on"
          placeholder="&lt;Insert repo description here&gt;"
          rows="4"
          monospace
          ?disabled=${this.readOnly}
          .text=${this.repoConfig?.description}
          @text-changed=${this.handleDescriptionTextChanged}
        ></gr-textarea>
      </fieldset>
    `;
  }

  private renderRepoOptions() {
    return html`
      <h3 id="Options" class="heading-3">Repository Options</h3>
      <fieldset id="options">
        ${this.renderState()} ${this.renderSubmitType()}
        ${this.renderContentMerges()} ${this.renderNewChange()}
        ${this.renderChangeId()} ${this.renderEnableSignedPush()}
        ${this.renderRequireSignedPush()} ${this.renderRejectImplicitMerges()}
        ${this.renderUnRegisteredCc()} ${this.renderPrivateByDefault()}
        ${this.renderWorkInProgressByDefault()} ${this.renderMaxGitObjectSize()}
        ${this.renderMatchAuthoredDateWithCommitterDate()}
        ${this.renderRejectEmptyCommit()}
      </fieldset>
      <h3 id="Options" class="heading-3">Contributor Agreements</h3>
      <fieldset id="agreements">
        ${this.renderContributorAgreement()} ${this.renderUseSignedOffBy()}
      </fieldset>
    `;
  }

  private renderState() {
    return html`
      <section>
        <span class="title">State</span>
        <span class="value">
          <gr-select
            id="stateSelect"
            .bindValue=${this.repoConfig?.state}
            @bind-value-changed=${this.handleStateSelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.states.map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderSubmitType() {
    return html`
      <section>
        <span class="title">Submit type</span>
        <span class="value">
          <gr-select
            id="submitTypeSelect"
            .bindValue=${this.repoConfig?.submit_type}
            @bind-value-changed=${this.handleSubmitTypeSelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatSubmitTypeSelect(this.repoConfig).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderContentMerges() {
    return html`
      <section>
        <span class="title">Allow content merges</span>
        <span class="value">
          <gr-select
            id="contentMergeSelect"
            .bindValue=${this.repoConfig?.use_content_merge?.configured_value}
            @bind-value-changed=${this.handleContentMergeSelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.use_content_merge
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderNewChange() {
    return html`
      <section>
        <span class="title">
          Create a new change for every commit not in the target branch
        </span>
        <span class="value">
          <gr-select
            id="newChangeSelect"
            .bindValue=${this.repoConfig
              ?.create_new_change_for_all_not_in_target?.configured_value}
            @bind-value-changed=${this.handleNewChangeSelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.create_new_change_for_all_not_in_target
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderChangeId() {
    return html`
      <section>
        <span class="title">Require Change-Id in commit message</span>
        <span class="value">
          <gr-select
            id="requireChangeIdSelect"
            .bindValue=${this.repoConfig?.require_change_id?.configured_value}
            @bind-value-changed=${this
              .handleRequireChangeIdSelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.require_change_id
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderEnableSignedPush() {
    return html`
      <section
        id="enableSignedPushSettings"
        class="repositorySettings ${this.repoConfig?.enable_signed_push
          ? 'showConfig'
          : ''}"
      >
        <span class="title">Enable signed push</span>
        <span class="value">
          <gr-select
            id="enableSignedPush"
            .bindValue=${this.repoConfig?.enable_signed_push?.configured_value}
            @bind-value-changed=${this.handleEnableSignedPushBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.enable_signed_push
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderRequireSignedPush() {
    return html`
      <section
        id="requireSignedPushSettings"
        class="repositorySettings ${this.repoConfig?.require_signed_push
          ? 'showConfig'
          : ''}"
      >
        <span class="title">Require signed push</span>
        <span class="value">
          <gr-select
            id="requireSignedPush"
            .bindValue=${this.repoConfig?.require_signed_push?.configured_value}
            @bind-value-changed=${this.handleRequireSignedPushBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.require_signed_push
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderRejectImplicitMerges() {
    return html`
      <section>
        <span class="title">
          Reject implicit merges when changes are pushed for review</span
        >
        <span class="value">
          <gr-select
            id="rejectImplicitMergesSelect"
            .bindValue=${this.repoConfig?.reject_implicit_merges
              ?.configured_value}
            @bind-value-changed=${this
              .handleRejectImplicitMergeSelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.reject_implicit_merges
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderUnRegisteredCc() {
    return html`
      <section>
        <span class="title">
          Enable adding unregistered users as reviewers and CCs on changes</span
        >
        <span class="value">
          <gr-select
            id="unRegisteredCcSelect"
            .bindValue=${this.repoConfig?.enable_reviewer_by_email
              ?.configured_value}
            @bind-value-changed=${this
              .handleUnRegisteredCcSelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.enable_reviewer_by_email
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderPrivateByDefault() {
    return html`
      <section>
        <span class="title"> Set all new changes private by default</span>
        <span class="value">
          <gr-select
            id="setAllnewChangesPrivateByDefaultSelect"
            .bindValue=${this.repoConfig?.private_by_default?.configured_value}
            @bind-value-changed=${this
              .handleSetAllNewChangesPrivateByDefaultSelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.private_by_default
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderWorkInProgressByDefault() {
    return html`
      <section>
        <span class="title">
          Set new changes to "work in progress" by default</span
        >
        <span class="value">
          <gr-select
            id="setAllNewChangesWorkInProgressByDefaultSelect"
            .bindValue=${this.repoConfig?.work_in_progress_by_default
              ?.configured_value}
            @bind-value-changed=${this
              .handleSetAllNewChangesWorkInProgressByDefaultSelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.work_in_progress_by_default
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderMaxGitObjectSize() {
    return html`
      <section>
        <span class="title">Maximum Git object size limit</span>
        <span class="value">
          <iron-input
            id="maxGitObjSizeIronInput"
            .bindValue=${this.repoConfig?.max_object_size_limit
              ?.configured_value}
            @bind-value-changed=${this.handleMaxGitObjSizeBindValueChanged}
          >
            <input
              id="maxGitObjSizeInput"
              type="text"
              ?disabled=${this.readOnly}
            />
          </iron-input>
          ${this.repoConfig?.max_object_size_limit?.value
            ? `effective: ${this.repoConfig.max_object_size_limit.value} bytes`
            : ''}
        </span>
      </section>
    `;
  }

  private renderMatchAuthoredDateWithCommitterDate() {
    return html`
      <section>
        <span class="title"
          >Match authored date with committer date upon submit</span
        >
        <span class="value">
          <gr-select
            id="matchAuthoredDateWithCommitterDateSelect"
            .bindValue=${this.repoConfig?.match_author_to_committer_date
              ?.configured_value}
            @bind-value-changed=${this
              .handleMatchAuthoredDateWithCommitterDateSelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.match_author_to_committer_date
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderRejectEmptyCommit() {
    return html`
      <section>
        <span class="title">Reject empty commit upon submit</span>
        <span class="value">
          <gr-select
            id="rejectEmptyCommitSelect"
            .bindValue=${this.repoConfig?.reject_empty_commit?.configured_value}
            @bind-value-changed=${this
              .handleRejectEmptyCommitSelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.reject_empty_commit
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderContributorAgreement() {
    return html`
      <section>
        <span class="title">
          Require a valid contributor agreement to upload</span
        >
        <span class="value">
          <gr-select
            id="contributorAgreementSelect"
            .bindValue=${this.repoConfig?.use_contributor_agreements
              ?.configured_value}
            @bind-value-changed=${this
              .handleUseContributorAgreementsBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.use_contributor_agreements
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderUseSignedOffBy() {
    return html`
      <section>
        <span class="title">Require Signed-off-by in commit message</span>
        <span class="value">
          <gr-select
            id="useSignedOffBySelect"
            .bindValue=${this.repoConfig?.use_signed_off_by?.configured_value}
            @bind-value-changed=${this
              .handleUseSignedOffBySelectBindValueChanged}
          >
            <select ?disabled=${this.readOnly}>
              ${this.formatBooleanSelect(
                this.repoConfig?.use_signed_off_by
              ).map(
                item => html`
                  <option value=${item.value}>${item.label}</option>
                `
              )}
            </select>
          </gr-select>
        </span>
      </section>
    `;
  }

  private renderPluginConfig() {
    const pluginData = this.computePluginData();
    return html` <div
      class="pluginConfig ${!pluginData || !pluginData.length ? 'hide' : ''}"
      @plugin-config-changed=${this.handlePluginConfigChanged}
    >
      <h3 class="heading-3">Plugins</h3>
      ${pluginData.map(
        item => html`
          <gr-repo-plugin-config
            .pluginData=${item}
            ?disabled=${this.readOnly}
          ></gr-repo-plugin-config>
        `
      )}
    </div>`;
  }

  override willUpdate(changedProperties: PropertyValues) {
    if (changedProperties.has('repo')) {
      this.loadRepo();
    }
    if (changedProperties.has('schemesObj')) {
      this.computeSchemesAndDefault();
    }
  }

  // private but used in test
  computePluginData() {
    if (!this.repoConfig || !this.repoConfig.plugin_config) return [];
    const pluginConfig = this.repoConfig.plugin_config;
    return Object.keys(pluginConfig).map(name => {
      return {name, config: pluginConfig[name]};
    });
  }

  // private but used in test
  async loadRepo() {
    if (!this.repo) return Promise.resolve();

    const promises = [];

    const errFn: ErrorCallback = response => {
      firePageError(response);
    };

    promises.push(
      this.restApiService.getLoggedIn().then(loggedIn => {
        if (loggedIn) {
          const repo = this.repo;
          if (!repo) throw new Error('undefined repo');
          this.restApiService.getRepo(repo).then(repo => {
            if (!repo?.web_links) return;
            this.weblinks = repo.web_links;
          });
          this.restApiService.getRepoAccess(repo).then(access => {
            if (!access || this.repo !== repo) {
              return;
            }

            // If the user is not an owner, is_owner is not a property.
            this.readOnly = !access[repo]?.is_owner;
          });
        }
      })
    );

    const repoConfigHelper = async () => {
      const config = await this.restApiService.getProjectConfig(
        this.repo as RepoName,
        errFn
      );
      if (!config) return;

      if (config.default_submit_type) {
        // The gr-select is bound to submit_type, which needs to be the
        // *configured* submit type. When default_submit_type is
        // present, the server reports the *effective* submit type in
        // submit_type, so we need to overwrite it before storing the
        // config in this.
        config.submit_type = config.default_submit_type.configured_value;
      }
      if (!config.state) {
        config.state = STATES.active.value;
      }
      // To properly check if the config has changed we need it to be a string
      // as it's converted to a string in the input.
      if (config.description === undefined) {
        config.description = '';
      }
      // To properly check if the config has changed we need it to be a string
      // as it's converted to a string in the input.
      if (config.max_object_size_limit.configured_value === undefined) {
        config.max_object_size_limit.configured_value = '';
      }
      this.repoConfig = config;
      this.originalConfig = deepClone(config) as ConfigInfo;
      this.loading = false;
    };
    promises.push(repoConfigHelper());

    const configHelper = async () => {
      const config = await this.restApiService.getConfig();
      if (!config) return;

      this.schemesObj = config.download.schemes;
    };
    promises.push(configHelper());

    await Promise.all(promises);
  }

  // private but used in test
  formatBooleanSelect(item?: InheritedBooleanInfo) {
    if (!item) return [];
    let inheritLabel = 'Inherit';
    if (!(item.inherited_value === undefined)) {
      inheritLabel = `Inherit (${item.inherited_value})`;
    }
    return [
      {
        label: inheritLabel,
        value: 'INHERIT',
      },
      {
        label: 'True',
        value: 'TRUE',
      },
      {
        label: 'False',
        value: 'FALSE',
      },
    ];
  }

  private formatSubmitTypeSelect(repoConfig?: ConfigInfo) {
    if (!repoConfig) return [];
    const allValues = Object.values(SUBMIT_TYPES);
    const type = repoConfig.default_submit_type;
    if (!type) {
      // Server is too old to report default_submit_type, so assume INHERIT
      // is not a valid value.
      return allValues;
    }

    let inheritLabel = 'Inherit';
    if (type.inherited_value) {
      inheritLabel = `Inherit (${type.inherited_value})`;
      for (const val of allValues) {
        if (val.value === type.inherited_value) {
          inheritLabel = `Inherit (${val.label})`;
          break;
        }
      }
    }
    return [
      {
        label: inheritLabel,
        value: 'INHERIT',
      },
      ...allValues,
    ];
  }

  // private but used in test
  formatRepoConfigForSave(repoConfig?: ConfigInfo): ConfigInput {
    if (!repoConfig) return {};
    const configInputObj: ConfigInput = {};
    for (const configKey of Object.keys(repoConfig)) {
      const key = configKey as keyof ConfigInfo;
      if (key === 'default_submit_type') {
        // default_submit_type is not in the input type, and the
        // configured value was already copied to submit_type by
        // _loadProject. Omit this property when saving.
        continue;
      }
      if (key === 'plugin_config') {
        configInputObj.plugin_config_values = repoConfig.plugin_config;
      } else if (typeof repoConfig[key] === 'object') {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const repoConfigObj: any = repoConfig[key];
        if (repoConfigObj.configured_value !== undefined) {
          configInputObj[key as keyof ConfigInput] =
            repoConfigObj.configured_value;
        }
      } else {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        configInputObj[key as keyof ConfigInput] = repoConfig[key] as any;
      }
    }
    return configInputObj;
  }

  // private but used in test
  async handleSaveRepoConfig() {
    if (!this.repoConfig || !this.repo)
      return Promise.reject(new Error('undefined repoConfig or repo'));
    await this.restApiService.saveRepoConfig(
      this.repo,
      this.formatRepoConfigForSave(this.repoConfig)
    );
    this.originalConfig = deepClone(this.repoConfig) as ConfigInfo;
    this.pluginConfigChanged = false;
    return;
  }

  private isEdited(
    original?: InheritedBooleanInfo | MaxObjectSizeLimitInfo,
    repo?: InheritedBooleanInfo | MaxObjectSizeLimitInfo
  ) {
    return original?.configured_value !== repo?.configured_value;
  }

  private hasConfigChanged() {
    const {repoConfig, originalConfig} = this;

    if (!repoConfig || !originalConfig) return false;

    if (originalConfig.description !== repoConfig.description) {
      return true;
    }
    if (originalConfig.state !== repoConfig.state) {
      return true;
    }
    if (originalConfig.submit_type !== repoConfig.submit_type) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.use_content_merge,
        repoConfig.use_content_merge
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.create_new_change_for_all_not_in_target,
        repoConfig.create_new_change_for_all_not_in_target
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.require_change_id,
        repoConfig.require_change_id
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.enable_signed_push,
        repoConfig.enable_signed_push
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.require_signed_push,
        repoConfig.require_signed_push
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.reject_implicit_merges,
        repoConfig.reject_implicit_merges
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.enable_reviewer_by_email,
        repoConfig.enable_reviewer_by_email
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.private_by_default,
        repoConfig.private_by_default
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.work_in_progress_by_default,
        repoConfig.work_in_progress_by_default
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.max_object_size_limit,
        repoConfig.max_object_size_limit
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.match_author_to_committer_date,
        repoConfig.match_author_to_committer_date
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.reject_empty_commit,
        repoConfig.reject_empty_commit
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.use_contributor_agreements,
        repoConfig.use_contributor_agreements
      )
    ) {
      return true;
    }
    if (
      this.isEdited(
        originalConfig.use_signed_off_by,
        repoConfig.use_signed_off_by
      )
    ) {
      return true;
    }

    return this.pluginConfigChanged;
  }

  private computeSchemesAndDefault() {
    this.schemes = !this.schemesObj ? [] : Object.keys(this.schemesObj).sort();
    if (this.schemes.length > 0) {
      if (!this.selectedScheme || !this.schemes.includes(this.selectedScheme)) {
        this.selectedScheme = this.schemes.sort()[0];
      }
    }
  }

  private computeCommands(
    repo?: RepoName,
    schemesObj?: SchemesInfoMap,
    selectedScheme?: string
  ) {
    if (!schemesObj || !repo || !selectedScheme) return [];
    if (!hasOwnProperty(schemesObj, selectedScheme)) return [];
    const commandObj = schemesObj[selectedScheme].clone_commands;
    const commands = [];
    for (const [title, command] of Object.entries(commandObj)) {
      commands.push({
        title,
        command: command
          .replace(/\${project}/gi, encodeURI(repo))
          .replace(
            /\${project-base-name}/gi,
            encodeURI(repo.substring(repo.lastIndexOf('/') + 1))
          ),
      });
    }
    return commands;
  }

  private computeChangesUrl(name?: RepoName) {
    if (!name) return '';
    return GerritNav.getUrlForProjectChanges(name);
  }

  // private but used in test
  handlePluginConfigChanged({
    detail: {name, config},
  }: {
    detail: {
      name: string;
      config: PluginParameterToConfigParameterInfoMap;
    };
  }) {
    if (this.repoConfig?.plugin_config) {
      this.repoConfig.plugin_config[name] = config;
      this.pluginConfigChanged = true;
      this.requestUpdate();
    }
  }

  private handleDescriptionTextChanged(e: BindValueChangeEvent) {
    if (!this.repoConfig || this.loading) return;
    this.repoConfig = {
      ...this.repoConfig,
      description: e.detail.value,
    };
    this.requestUpdate();
  }

  private handleStateSelectBindValueChanged(e: BindValueChangeEvent) {
    if (!this.repoConfig || this.loading) return;
    this.repoConfig = {
      ...this.repoConfig,
      state: e.detail.value as ProjectState,
    };
    this.requestUpdate();
  }

  private handleSubmitTypeSelectBindValueChanged(e: BindValueChangeEvent) {
    if (!this.repoConfig || this.loading) return;
    this.repoConfig = {
      ...this.repoConfig,
      submit_type: e.detail.value as SubmitType,
    };
    this.requestUpdate();
  }

  private handleContentMergeSelectBindValueChanged(e: BindValueChangeEvent) {
    if (!this.repoConfig?.use_content_merge || this.loading) return;
    this.repoConfig.use_content_merge.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleNewChangeSelectBindValueChanged(e: BindValueChangeEvent) {
    if (
      !this.repoConfig?.create_new_change_for_all_not_in_target ||
      this.loading
    )
      return;
    this.repoConfig.create_new_change_for_all_not_in_target.configured_value = e
      .detail.value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleRequireChangeIdSelectBindValueChanged(e: BindValueChangeEvent) {
    if (!this.repoConfig?.require_change_id || this.loading) return;
    this.repoConfig.require_change_id.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleEnableSignedPushBindValueChanged(e: BindValueChangeEvent) {
    if (!this.repoConfig?.enable_signed_push || this.loading) return;
    this.repoConfig.enable_signed_push.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleRequireSignedPushBindValueChanged(e: BindValueChangeEvent) {
    if (!this.repoConfig?.require_signed_push || this.loading) return;
    this.repoConfig.require_signed_push.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleRejectImplicitMergeSelectBindValueChanged(
    e: BindValueChangeEvent
  ) {
    if (!this.repoConfig?.reject_implicit_merges || this.loading) return;
    this.repoConfig.reject_implicit_merges.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleUnRegisteredCcSelectBindValueChanged(e: BindValueChangeEvent) {
    if (!this.repoConfig?.enable_reviewer_by_email || this.loading) return;
    this.repoConfig.enable_reviewer_by_email.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleSetAllNewChangesPrivateByDefaultSelectBindValueChanged(
    e: BindValueChangeEvent
  ) {
    if (!this.repoConfig?.private_by_default || this.loading) return;
    this.repoConfig.private_by_default.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleSetAllNewChangesWorkInProgressByDefaultSelectBindValueChanged(
    e: BindValueChangeEvent
  ) {
    if (!this.repoConfig?.work_in_progress_by_default || this.loading) return;
    this.repoConfig.work_in_progress_by_default.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleMaxGitObjSizeBindValueChanged(e: BindValueChangeEvent) {
    if (!this.repoConfig?.max_object_size_limit || this.loading) return;
    this.repoConfig.max_object_size_limit.value = e.detail.value;
    this.repoConfig.max_object_size_limit.configured_value = e.detail.value;
    this.requestUpdate();
  }

  private handleMatchAuthoredDateWithCommitterDateSelectBindValueChanged(
    e: BindValueChangeEvent
  ) {
    if (!this.repoConfig?.match_author_to_committer_date || this.loading)
      return;
    this.repoConfig.match_author_to_committer_date.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleRejectEmptyCommitSelectBindValueChanged(
    e: BindValueChangeEvent
  ) {
    if (!this.repoConfig?.reject_empty_commit || this.loading) return;
    this.repoConfig.reject_empty_commit.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleUseContributorAgreementsBindValueChanged(
    e: BindValueChangeEvent
  ) {
    if (!this.repoConfig?.use_contributor_agreements || this.loading) return;
    this.repoConfig.use_contributor_agreements.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }

  private handleUseSignedOffBySelectBindValueChanged(e: BindValueChangeEvent) {
    if (!this.repoConfig?.use_signed_off_by || this.loading) return;
    this.repoConfig.use_signed_off_by.configured_value = e.detail
      .value as InheritedBooleanInfoConfiguredValue;
    this.requestUpdate();
  }
}
