import { __esDecorate, __runInitializers } from "tslib";
import { html, nothing } from 'lit';
import { property, state } from 'lit/decorators.js';
import { live } from 'lit/directives/live.js';
import { Certificate } from '@api-client/core/models/ClientCertificate.js';
import { CertificateFile } from '@api-client/core/models/CertificateFile.js';
import { Events } from '../../events/Events.js';
import ApiElement from '../ApiElement.js';
import styles from './CertificateAdd.styles.js';
import { getFileName } from '../../lib/files/Utils.js';
// import type { IFileFilter, IOpenFileDialogInit } from '../../bindings/base/FileBindings.js'
import { SnackNotifications } from '../../md/notification/SnackNotifications.js';
import '../../md/segmented-button/ui-segmented-button.js';
import '../../md/segmented-button/ui-segmented-button-set.js';
import '../../md/text-field/ui-filled-text-field.js';
import '../../md/button/ui-button.js';
import '../../md/icons/ui-icon.js';
import '../../md/progress/ui-progress.js';
let CertificateAdd = (() => {
    let _classSuper = ApiElement;
    let _importType_decorators;
    let _importType_initializers = [];
    let _importType_extraInitializers = [];
    let _folder_decorators;
    let _folder_initializers = [];
    let _folder_extraInitializers = [];
    let _space_decorators;
    let _space_initializers = [];
    let _space_extraInitializers = [];
    let _working_decorators;
    let _working_initializers = [];
    let _working_extraInitializers = [];
    let _certificateFile_decorators;
    let _certificateFile_initializers = [];
    let _certificateFile_extraInitializers = [];
    let _keyFile_decorators;
    let _keyFile_initializers = [];
    let _keyFile_extraInitializers = [];
    return class CertificateAdd extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _importType_decorators = [property({ type: String })];
            _folder_decorators = [property({ type: String })];
            _space_decorators = [property({ type: String })];
            _working_decorators = [state()];
            _certificateFile_decorators = [state()];
            _keyFile_decorators = [state()];
            __esDecorate(this, null, _importType_decorators, { kind: "accessor", name: "importType", static: false, private: false, access: { has: obj => "importType" in obj, get: obj => obj.importType, set: (obj, value) => { obj.importType = value; } }, metadata: _metadata }, _importType_initializers, _importType_extraInitializers);
            __esDecorate(this, null, _folder_decorators, { kind: "accessor", name: "folder", static: false, private: false, access: { has: obj => "folder" in obj, get: obj => obj.folder, set: (obj, value) => { obj.folder = value; } }, metadata: _metadata }, _folder_initializers, _folder_extraInitializers);
            __esDecorate(this, null, _space_decorators, { kind: "accessor", name: "space", static: false, private: false, access: { has: obj => "space" in obj, get: obj => obj.space, set: (obj, value) => { obj.space = value; } }, metadata: _metadata }, _space_initializers, _space_extraInitializers);
            __esDecorate(this, null, _working_decorators, { kind: "accessor", name: "working", static: false, private: false, access: { has: obj => "working" in obj, get: obj => obj.working, set: (obj, value) => { obj.working = value; } }, metadata: _metadata }, _working_initializers, _working_extraInitializers);
            __esDecorate(this, null, _certificateFile_decorators, { kind: "accessor", name: "certificateFile", static: false, private: false, access: { has: obj => "certificateFile" in obj, get: obj => obj.certificateFile, set: (obj, value) => { obj.certificateFile = value; } }, metadata: _metadata }, _certificateFile_initializers, _certificateFile_extraInitializers);
            __esDecorate(this, null, _keyFile_decorators, { kind: "accessor", name: "keyFile", static: false, private: false, access: { has: obj => "keyFile" in obj, get: obj => obj.keyFile, set: (obj, value) => { obj.keyFile = value; } }, metadata: _metadata }, _keyFile_initializers, _keyFile_extraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        static get styles() {
            return styles;
        }
        #importType_accessor_storage = __runInitializers(this, _importType_initializers, 'pem'
        /**
         * The parent folder where to insert the imported certificate.
         * @attribute
         */
        );
        /**
         * The type of the certificate to import.
         * @attribute
         */
        get importType() { return this.#importType_accessor_storage; }
        set importType(value) { this.#importType_accessor_storage = value; }
        #folder_accessor_storage = (__runInitializers(this, _importType_extraInitializers), __runInitializers(this, _folder_initializers, void 0));
        /**
         * The parent folder where to insert the imported certificate.
         * @attribute
         */
        get folder() { return this.#folder_accessor_storage; }
        set folder(value) { this.#folder_accessor_storage = value; }
        #space_accessor_storage = (__runInitializers(this, _folder_extraInitializers), __runInitializers(this, _space_initializers, void 0));
        /**
         * The current workspace for the file.
         * @attribute
         */
        get space() { return this.#space_accessor_storage; }
        set space(value) { this.#space_accessor_storage = value; }
        #working_accessor_storage = (__runInitializers(this, _space_extraInitializers), __runInitializers(this, _working_initializers, void 0));
        /**
         * When an IO operation is in progress.
         */
        get working() { return this.#working_accessor_storage; }
        set working(value) { this.#working_accessor_storage = value; }
        #certificateFile_accessor_storage = (__runInitializers(this, _working_extraInitializers), __runInitializers(this, _certificateFile_initializers, void 0));
        get certificateFile() { return this.#certificateFile_accessor_storage; }
        set certificateFile(value) { this.#certificateFile_accessor_storage = value; }
        #keyFile_accessor_storage = (__runInitializers(this, _certificateFile_extraInitializers), __runInitializers(this, _keyFile_initializers, void 0));
        get keyFile() { return this.#keyFile_accessor_storage; }
        set keyFile(value) { this.#keyFile_accessor_storage = value; }
        /**
         * The password for the certificate
         */
        certificatePassword = __runInitializers(this, _keyFile_extraInitializers);
        /**
         * The password for the key.
         */
        keyPassword;
        /**
         * The user entered certificate name.
         */
        certificateName;
        get hasKeyImport() {
            return this.importType === 'pem';
        }
        get hasCertificatePasswordInput() {
            return this.importType === 'p12';
        }
        handleViewSelection(e) {
            if (!e.detail.selected) {
                return;
            }
            const button = e.detail.button;
            const type = button.dataset.value;
            if (type) {
                this.importType = type;
            }
        }
        handleNameChange(e) {
            const input = e.target;
            this.certificateName = input.value;
        }
        handleCertificatePasswordChange(e) {
            const input = e.target;
            this.certificatePassword = input.value;
        }
        handleKeyPasswordChange(e) {
            const input = e.target;
            this.keyPassword = input.value;
        }
        handleSelectCertificate() {
            this.selectCertificateFLow();
        }
        handleSelectKey() {
            this.selectKeyFLow();
        }
        async selectCertificateFLow() {
            throw new Error(`Not yet implemented`);
            // this.working = true
            // const options: IOpenFileDialogInit = {
            //   multiple: false,
            //   title: 'Select a certificate file',
            //   filters: [
            //     {
            //       description: 'Certificate files',
            //       accept: {},
            //     },
            //   ],
            // }
            // const filters = options.filters as IFileFilter[]
            // if (this.importType === 'p12') {
            //   filters[0].accept = {
            //     'application/x-pkcs12': ['.p12', '.pfx'],
            //   }
            // } else {
            //   filters[0].accept = {
            //     'application/x-pem-file': ['.pem', '.crt', '.cer', '.key'],
            //   }
            // }
            // const pickResult = await Events.Filesystem.requestOpenFile(options, this)
            // if (!pickResult || pickResult.canceled) {
            //   this.working = false
            //   return
            // }
            // const [path] = pickResult.filePath as string[]
            // const readResult = await Events.Filesystem.readFile(path, { returnType: 'buffer', dispose: true }, this)
            // if (!readResult) {
            //   this.working = false
            //   return
            // }
            // const fileName = getFileName.getFileName(path)
            // this.certificateFile = {
            //   fileName,
            //   contents: readResult as ArrayBuffer,
            // }
            // this.working = false
        }
        async selectKeyFLow() {
            throw new Error(`Not yet implemented`);
            // this.working = true
            // const options: IOpenFileDialogInit = {
            //   multiple: false,
            //   title: 'Select a key file',
            //   filters: [
            //     {
            //       description: 'Certificate key files',
            //       accept: {
            //         'application/x-pem-file': ['.pem', '.crt', '.cer', '.key'],
            //       },
            //     },
            //   ],
            // }
            // const pickResult = await Events.Filesystem.requestOpenFile(options, this)
            // if (!pickResult || pickResult.canceled) {
            //   this.working = false
            //   return
            // }
            // const [path] = pickResult.filePath as string[]
            // const readResult = await Events.Filesystem.readFile(path, { returnType: 'buffer', dispose: true }, this)
            // if (!readResult) {
            //   this.working = false
            //   return
            // }
            // const fileName = getFileName.getFileName(path)
            // this.keyFile = {
            //   fileName,
            //   contents: readResult as ArrayBuffer,
            // }
            // this.working = false
        }
        isValidDropTarget(dt) {
            const types = Array.from(dt.types);
            return types.includes('Files');
        }
        handleFileDragEnter(e) {
            const dt = e.dataTransfer;
            if (!this.isValidDropTarget(dt)) {
                return;
            }
            e.preventDefault();
            dt.dropEffect = 'copy';
            const node = e.currentTarget;
            node.classList.add('dragover');
        }
        handleFileDragLeave(e) {
            const dt = e.dataTransfer;
            if (!this.isValidDropTarget(dt)) {
                return;
            }
            e.preventDefault();
            dt.dropEffect = 'none';
            const node = e.currentTarget;
            node.classList.remove('dragover');
        }
        handleFileDragOver(e) {
            const dt = e.dataTransfer;
            if (!this.isValidDropTarget(dt)) {
                return;
            }
            e.preventDefault();
            const node = e.currentTarget;
            node.classList.add('dragover');
        }
        handleFileDrop(e) {
            const dt = e.dataTransfer;
            e.preventDefault();
            const node = e.currentTarget;
            node.classList.remove('dragover');
            const file = dt.files[0];
            if (!file) {
                return;
            }
            const { kind } = node.dataset;
            if (!kind) {
                return;
            }
            this.processDroppedFile(file, kind);
        }
        async processDroppedFile(file, kind) {
            this.working = true;
            const buff = await file.arrayBuffer();
            const fileName = getFileName(file.name);
            if (kind === 'certificate') {
                this.certificateFile = {
                    fileName,
                    contents: buff,
                };
            }
            else if (kind === 'key') {
                this.keyFile = {
                    fileName,
                    contents: buff,
                };
            }
            this.working = false;
        }
        handleCancel() {
            this.dispatchEvent(new Event('close'));
        }
        handleImport() {
            this.submit();
        }
        async submit() {
            const invalid = this.reportValidity();
            if (invalid) {
                return;
            }
            const { certificateFile, certificateName, certificatePassword, keyFile, keyPassword, folder } = this;
            const cert = this.importType === 'p12'
                ? Certificate.fromP12(certificateFile?.contents, certificateName, certificatePassword)
                : Certificate.fromPem(certificateFile?.contents, keyFile?.contents, certificateName, keyPassword);
            const file = CertificateFile.fromCertificate(cert);
            await Events.Store.File.create(file.toJSON(), cert.toJSON(), { parent: folder }, this);
            this.handleCancel();
        }
        reportValidity() {
            const inputs = Array.from(this.shadowRoot.querySelectorAll('ui-filled-text-field'));
            let invalid = false;
            inputs.forEach((input) => {
                const inputResult = input.reportValidity();
                if (!inputResult) {
                    invalid = true;
                }
            });
            if (!invalid) {
                if (!this.certificateFile) {
                    invalid = true;
                    SnackNotifications.notify(`Certificate file is required.`);
                }
                if (!invalid && this.hasKeyImport && !this.keyFile) {
                    invalid = true;
                    SnackNotifications.notify(`The key file is required.`);
                }
            }
            return invalid;
        }
        render() {
            return html `
      <div class="form">
        ${this.renderProgress()} ${this.renderViewToggle()} ${this.renderNameInput()} ${this.renderCertificateFile()}
        ${this.renderCertificatePasswordInput()} ${this.renderKeyFile()} ${this.renderKeyPasswordInput()}
        ${this.renderImportButton()}
      </div>
    `;
        }
        renderViewToggle() {
            const { importType } = this;
            return html `
      <div class="view-toggle">
        <ui-segmented-button-set @select="${this.handleViewSelection}">
          <ui-segmented-button
            .selected="${importType === 'pem'}"
            title="Import a certificate in PEM format"
            data-value="pem"
            >PEM</ui-segmented-button
          >
          <ui-segmented-button
            .selected="${importType === 'p12'}"
            title="Import a bundled PFX or PKCS12 encoded private key and certificate"
            data-value="p12"
            >PFX or PKCS12</ui-segmented-button
          >
        </ui-segmented-button-set>
      </div>
    `;
        }
        renderNameInput() {
            const { certificateName = '' } = this;
            return html `
      <div class="form-input">
        <ui-filled-text-field
          required
          name="name"
          .value="${live(certificateName)}"
          label="Certificate name"
          @change="${this.handleNameChange}"
          invalidText="The name is required"
        ></ui-filled-text-field>
      </div>
    `;
        }
        renderCertificateFile() {
            const { certificateFile } = this;
            return html `
      <div
        class="cert-file"
        data-kind="certificate"
        @dragenter="${this.handleFileDragEnter}"
        @dragleave="${this.handleFileDragLeave}"
        @dragover="${this.handleFileDragOver}"
        @drop="${this.handleFileDrop}"
      >
        <p class="body-medium">Select or drop a certificate file here.</p>
        <ui-button color="tonal" @click="${this.handleSelectCertificate}" class="select-button"
          >Select certificate file</ui-button
        >
        ${certificateFile
                ? html `<span class="cert-info body-medium">${certificateFile.fileName}</span>`
                : html `<span class="missing body-medium"
              ><ui-icon role="presentation" icon="warning" class="missing-icon"></ui-icon>Certificate is not
              selected</span
            >`}
      </div>
    `;
        }
        renderCertificatePasswordInput() {
            const { certificatePassword = '' } = this;
            if (!this.hasCertificatePasswordInput) {
                return nothing;
            }
            return html `
      <div class="form-input">
        <ui-filled-text-field
          name="certificatePassword"
          type="password"
          .value="${live(certificatePassword)}"
          label="Certificate password"
          @change="${this.handleCertificatePasswordChange}"
          supportingText="Optional password for the certificate"
        ></ui-filled-text-field>
      </div>
    `;
        }
        renderKeyFile() {
            if (!this.hasKeyImport) {
                return nothing;
            }
            const { keyFile } = this;
            return html `
      <div
        class="cert-file"
        data-kind="key"
        @dragenter="${this.handleFileDragEnter}"
        @dragleave="${this.handleFileDragLeave}"
        @dragover="${this.handleFileDragOver}"
        @drop="${this.handleFileDrop}"
      >
        <p class="body-medium">Select or drop a key file here.</p>
        <ui-button color="tonal" @click="${this.handleSelectKey}" class="select-button">Select key file</ui-button>
        ${keyFile
                ? html `<span class="cert-info body-medium">${keyFile.fileName}</span>`
                : html `<span class="missing body-medium"
              ><ui-icon role="presentation" icon="warning" class="missing-icon"></ui-icon>Key is not selected</span
            >`}
      </div>
    `;
        }
        renderKeyPasswordInput() {
            if (!this.hasKeyImport) {
                return nothing;
            }
            const { keyPassword = '' } = this;
            return html `
      <div class="form-input">
        <ui-filled-text-field
          name="keyPassword"
          type="password"
          .value="${live(keyPassword)}"
          label="Key password"
          @change="${this.handleKeyPasswordChange}"
          supportingText="Optional password for the key"
        ></ui-filled-text-field>
      </div>
    `;
        }
        renderImportButton() {
            return html `
      <div class="form-action">
        <ui-button color="filled" @click="${this.handleImport}">Import</ui-button>
        <ui-button color="text" @click="${this.handleCancel}">Cancel</ui-button>
      </div>
    `;
        }
        renderProgress() {
            if (!this.working) {
                return nothing;
            }
            return html `<ui-progress indeterminate class="working"></ui-progress>`;
        }
    };
})();
/**
 * An element that renders a certificate import UI.
 *
 * Notes for implementation:
 * - `p12` is a single file, may have a passphrase
 * - `pem` is 2 files: the certificate and the key
 * - `pem` may have a `passphrase` on the key but not on the certificate.
 */
export default CertificateAdd;
//# sourceMappingURL=CertificateAdd.element.js.map