class CCPInputWidgetController extends HTMLElement {

  #data = null;

  constructor() {
    super()
  }

  connectedCallback() {
    this.#data = JSON.parse(atob(this.getAttribute("input")))

    if (this.isChecklist()) {

      const opts = this.#data.schema.enum.join(",")
      this.innerHTML += `<d4s-ccp-input-checklist readonly="${this.#data.schema.readOnly}" options="${opts}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-checklist>`
      this.querySelector("d4s-ccp-input-checklist").default = this.#data.schema.default

    } else if (this.isEnum()) {

      const opts = this.#data.schema.enum.join(",")
      this.innerHTML += `<d4s-ccp-input-enum readonly="${this.#data.schema.readOnly}" options="${opts}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-enum>`
      this.querySelector("d4s-ccp-input-enum").default = this.#data.schema.default

    } else if (this.isCode()) {
      
      this.innerHTML += `<d4s-ccp-input-textarea readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-textarea>`
      this.querySelector("d4s-ccp-input-textarea").default = this.#data.schema.default

    } else if (this.isDateTime()) {
      
      const t = this.#data.schema.format.toLowerCase() === "datetime" ?
        "datetime-local" : this.#data.schema.format.toLowerCase()
      this.innerHTML += `<d4s-ccp-input-simple type="${t}" readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-simple>`
      this.querySelector("d4s-ccp-input-simple").default = this.#data.schema.default

    } else if (this.isFile()) {
      
      this.innerHTML += `<d4s-ccp-input-file readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-file>`
      this.querySelector("d4s-ccp-input-file").default = this.#data.schema.default

    } else if (this.isRemoteFile()) {
      
      this.innerHTML += `<d4s-ccp-input-remotefile readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-remotefile>`
      this.querySelector("d4s-ccp-input-remotefile").default = this.#data.schema.default

    } else if (this.isSecret()) {
      
      this.innerHTML += `<d4s-ccp-input-secret readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs }" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-secret>`
      this.querySelector("d4s-ccp-input-secret").default = this.#data.schema.default

    } else if (this.isBoolean()) {
      
      this.innerHTML += `<d4s-ccp-input-boolean readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-boolean>`
      this.querySelector("d4s-ccp-input-boolean").default = this.#data.schema.default

    } else if (this.isNumber()) {
      
      this.innerHTML += `<d4s-ccp-input-simple type="number" readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-simple>`
      this.querySelector("d4s-ccp-input-simple").default = this.#data.schema.default

    } else {
      
      this.innerHTML += `<d4s-ccp-input-simple readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-simple>`
      this.querySelector("d4s-ccp-input-simple").default = this.#data.schema.default

    }
  }

  set value(value) {
    this.firstElementChild.value = value
  }

  get value() {
    return this.firstElementChild.value.length === 1 ?
      this.firstElementChild.value[0] :
      this.firstElementChild.value
  }

  get name() {
    return this.firstElementChild.name
  }

  isChecklist() {
    return this.isEnum() && (this.#data.schema.format === "checklist")
  }

  isNumber() {
    return (this.#data.schema.type === "string") &&
      ("format" in this.#data.schema) &&
      (this.#data.schema.format != null) &&
      (this.#data.schema.format.toLowerCase() === "number")
  }

  isBoolean() {
    return (this.#data.schema.type === "string") &&
      ("format" in this.#data.schema) &&
      (this.#data.schema.format != null) &&
      (this.#data.schema.format.toLowerCase() === "boolean")
  }

  isEnum() {
    return (this.#data.schema.type === "string") && ("enum" in this.#data.schema)
  }

  isSecret() {
    return (this.#data.schema.type === "string") &&
      ("format" in this.#data.schema) &&
      (this.#data.schema.format != null) &&
      (this.#data.schema.format.toLowerCase() === "secret")
  }

  isCode() {
    return (this.#data.schema.type === "string") &&
      ("format" in this.#data.schema) &&
      (this.#data.schema.format != null) &&
      (this.#data.schema.format.toLowerCase() === "code")
  }

  isFile() {
    return (this.#data.schema.type === "string") &&
      ("format" in this.#data.schema) &&
      (this.#data.schema.format != null) &&
      (this.#data.schema.format.toLowerCase() === "file")
  }

  isRemoteFile() {
    return (this.#data.schema.type === "string") &&
      ("format" in this.#data.schema) &&
      (this.#data.schema.format != null) &&
      (this.#data.schema.format.toLowerCase() === "remotefile")
  }

  isDateTime() {
    return (this.#data.schema.type === "string") &&
      ("format" in this.#data.schema) &&
      (this.#data.schema.format != null) &&
      (["date", "time", "datetime"].indexOf(this.#data.schema.format.toLowerCase()) !== -1)
  }
}
window.customElements.define('d4s-ccp-input', CCPInputWidgetController);

class CCPBaseInputWidgetController extends HTMLElement {
  #rootdoc = null;
  #minOccurs = 1;
  #maxOccurs = 1;
  #description = ""
  #title = ""
  #name = ""
  #default = null
  #options = null
  #value = null
  #readonly = false

  //useful to avoid having a custom element for every basic input type
  #type = null

  #count = 1

  constructor() {
    super()
    this.#rootdoc = this//this.attachShadow({ mode: "open" });
    this.#name = this.getAttribute("name")
    this.#title = this.getAttribute("title")
    this.#description = this.getAttribute("description")
    //this.#default = this.getAttribute("default")
    this.#minOccurs = Number(this.getAttribute("minoccurs") ? this.getAttribute("minoccurs") : 1)
    this.#maxOccurs = Number(this.getAttribute("maxoccurs") ? this.getAttribute("maxoccurs") : 1)
    this.#maxOccurs = Math.max(this.#minOccurs, this.#maxOccurs)
    this.#readonly = this.getAttribute("readonly") === "true"

    // coalesce all basic input types
    this.#type = this.getAttribute("type")

    // Handle enum case
    this.#options = (this.getAttribute("options") ? this.getAttribute("options").split(",") : null)

    //this.value = Array(Math.max(this.#minOccurs, 1)).fill(this.#default)
  }

  set default(def){
    this.#default = def
    const defarr = Array.isArray(def) ? def : [def]
    const min = Math.max(this.#minOccurs, 1)
    var v = []
    for(let j=0; j < this.#maxOccurs; j++){
      if(j < defarr.length){
        v.push(defarr[j])
      }else if(j < min){
        v.push(defarr[defarr.length - 1])
      }
    }
    this.value = v
  }

  setValue(v) {
    this.#value = v
    this.render()
  }

  set value(v) {
    const actual = Array.isArray(v) ? v : [v]
    if (actual.length < this.#minOccurs || actual.length > this.#maxOccurs) {
      throw `Value with length ${v.length} does not respect bounds [${this.minOccurs},${this.maxOccurs}]`
    }
    this.#value = actual
    this.render()
  }

  get value() {
    return this.#value
  }

  get rootdoc() {
    return this.#rootdoc
  }

  get required() {
    return this.#minOccurs > 0
  }

  get readonly() {
    return this.#readonly
  }

  isIncrementable() {
    return this.#value.length < this.#maxOccurs
  }

  isDecrementable() {
    return this.#value.length > this.#minOccurs && this.#value.length > 1
  }

  get count() {
    return this.#count
  }

  get name() {
    return this.#name
  }

  get title() {
    return this.#title
  }

  get description() {
    return this.#description
  }

  get default() {
    return this.#default
  }

  get options() {
    return this.#options
  }

  get type() {
    return this.#type
  }

  renderPlusMinus() {
    this.rootdoc.querySelector("div[name=plusminus]").innerHTML = `
        ${this.isIncrementable() ? `<span name="plus" title="add one" class="badge text-success border-success btn">+</span>` : ``}
        ${this.isDecrementable() ? `<span name="minus" title="remove one" class="badge border border-danger  text-danger btn">-</span>` : ``}
    `
  }

  renderContent() {
    this.rootdoc.querySelector("div[name=content]").innerHTML = this.content()
  }

  render() {
    this.rootdoc.innerHTML = `
      <div name="root" class="my-3 ccp-input-widget form-field row">
        <label class="form-label">
          <div class="d-flex justify-content-between">
            <div>
              ${this.required ? `<span title="Required" class="p-1 text-danger">*</span>` : ``}
              ${this.title}
            </div>
            <div name="tools" class="d-flex" style="gap:2px">
              <div name="plusminus">
              </div>
            </div>
          </div>
          <div>
            <small class="text-muted">${atob(this.#description)}</small>
          </div>
          <div name="content">
          </div>
        </label>
     </div>
    `

    this.renderPlusMinus()
    this.renderContent()

    this.#rootdoc.querySelector("div[name=root]").addEventListener("click", ev => {
      const src = ev.target.getAttribute("name")
      if (src === "plus") {
        this.#value.push(this.#value[this.#value.length - 1])
        this.renderPlusMinus()
        this.renderContent()
        ev.preventDefault()
      } else if (src === "minus") {
        this.#value.pop()
        this.renderPlusMinus()
        this.renderContent()
        ev.preventDefault()
      }
    })
  }
}

class CCPSimpleInputWidgetController extends CCPBaseInputWidgetController {

  constructor() {
    super()
  }

  connectedCallback() {
    this.rootdoc.addEventListener("input", ev => {
      if (ev.target.getAttribute("name") === this.name) {
        const index = Number(ev.target.getAttribute("data-index"))
        this.value[index] = ev.target.value
      }
    })
  }

  content() {
    if (this.value.length <= 1) {
      return `<input data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>`
    }
    var out =
      this.value.map((c, i) => {
        return `
          <input name="${this.name}" value="${c}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>
        `
      }).join("\n")
    return out
  }
}
window.customElements.define('d4s-ccp-input-simple', CCPSimpleInputWidgetController);

class CCPEnumInputWidgetController extends CCPBaseInputWidgetController {

  constructor() {
    super()
  }

  connectedCallback() {
    this.rootdoc.addEventListener("change", ev => {
      if (ev.target.getAttribute("name") === this.name) {
        const index = Number(ev.target.getAttribute("data-index"))
        this.value[index] = ev.target.value
      }
    })
  }

  content() {
    if (this.value.length <= 1) {
      const opts = this.options ?
        this.options.map(o => `<option value="${o}" ${this.value.length && o === this.value[0] ? 'selected' : ''}>${o}</option>`).join("\n") :
        ''
      return `<select data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'disabled' : ''} ${this.required ? 'required' : ''}>${opts}</select>`
    }
    var out =
      this.value.map((v, i) => {
        const opts = this.options ?
          this.options.map(o => `<option value="${o}" ${o === v ? 'selected' : ''}>${o}</option>`).join("\n") :
          ''
        return `
          <select data-index="${i}" value="${v}" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'disabled' : ''} ${this.required ? 'required' : ''}>${opts}</select>
        `
      }).join("\n")
    return out
  }
}
window.customElements.define('d4s-ccp-input-enum', CCPEnumInputWidgetController);

class CCPChecklistInputWidgetController extends CCPBaseInputWidgetController {

  constructor() {
    super()
  }

  connectedCallback() {
    this.rootdoc.addEventListener("change", ev => {
      if (ev.target.getAttribute("name") === this.name) {
        const index = Number(ev.target.getAttribute("data-index"))

        const elems = Array.prototype.slice.call(ev.currentTarget.querySelectorAll(`input[name='${this.name}'][data-index='${index}']`))

        this.value[index] = elems.filter(e => e.checked).map(e => e.value).join(",")
      }
    })
  }

  buildOpts(index, selections) {
    return this.options ? this.options.map(o => `
        <div class="form-check form-switch form-check-inline">
          <label>${o}</label>
          <input data-index="${index}" class="form-check-input" type="checkbox" name="${this.name}" value="${o}" ${this.readonly ? 'readonly' : ''} ${selections.indexOf(o) > -1 ? 'checked' : ''}/></div>
      `).join("\n") :
      `
        <div class="form-check form-switch form-check-inline">
          <span class="muted text-danger">No options supplied</span>
        </div>
      `
  }

  content() {
    if (this.value.length === 1) {
      const opts = this.buildOpts(0, this.value.length ? this.value[0].split(",") : [])
      return `
        <div class="my-2">
          ${opts}
        </div>
      `
    }
    var out =
      this.value.map((c, i) => {
        const opts = this.buildOpts(i, c.split(","))
        return `
          <div class="my-2">
            ${opts}
          </div>
        `
      }).join("\n")
    return out
  }
}
window.customElements.define('d4s-ccp-input-checklist', CCPChecklistInputWidgetController);

class CCPBooleanInputWidgetController extends CCPBaseInputWidgetController {

  constructor() {
    super()
  }

  connectedCallback() {
    this.rootdoc.addEventListener("input", ev => {
      if (ev.target.getAttribute("name") === this.name) {
        const index = Number(ev.target.getAttribute("data-index"))
        this.value[index] = ev.target.checked
      }
    })
  }

  content() {
    if (this.value.length <= 1) {
      return `
        <div class="my-2 form-check form-switch form-check-inline">
          <input data-index="0" value="${this.value.length ? this.value[0] : false}" class="my-2 form-check-input" type="checkbox" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.value[0] === "true" || this.value[0] === true ? 'checked' : ''} value="${this.value[0]}"/>
        </div>
      `
    }
    var out =
      this.value.map((c, i) => {
        return `
          <div class="my-2 form-check form-switch form-check-inline">
            <input data-index="${i}" value="${c}" class="my-2 form-check-input" type="checkbox" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${c === "true"  || c === true ? 'checked' : ''}/>
          </div>
        `
      }).join("\n")
    return out
  }
}
window.customElements.define('d4s-ccp-input-boolean', CCPBooleanInputWidgetController);

class CCPTextAreaWidgetController extends CCPBaseInputWidgetController {

  constructor() {
    super()
  }

  connectedCallback() {
    this.rootdoc.addEventListener("input", ev => {
      if (ev.target.getAttribute("name") === this.name) {
        const index = Number(ev.target.getAttribute("data-index"))
        this.value[index] = ev.target.value
      }
    })
  }

  content() {
    if (this.value.length <= 1) {
      return `<textarea data-index="0" class="my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" rows="5" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}>${this.value.length ? this.value[0] : ''}</textarea>`
    }
    var out =
      this.value.map((c, i) => {
        return `
          <textarea name="${this.name}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" rows="5" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}>${c}</textarea>
        `
      }).join("\n")
    return out
  }
}
window.customElements.define('d4s-ccp-input-textarea', CCPTextAreaWidgetController);

class CCPFileInputWidgetController extends CCPBaseInputWidgetController {

  constructor() {
    super()
  }

  connectedCallback() {
    this.rootdoc.addEventListener("change", ev => {
      const tgt = ev.target
      if (tgt.getAttribute("name") === this.name) {
        const index = Number(tgt.getAttribute("data-index"))
        const file = ev.target.files[0]
        if (file.size > 100 * 1024) {
          alert("This input allows only small files (100K). Use references instead ")
          ev.stopPropagation()
          ev.preventDefault()
          tgt.value = null
          return false
        }
        const reader = new FileReader()
        reader.addEventListener('load', ev => {
          let encoded = ev.target.result.toString().replace(/^data:(.*,)?/, '');
          if ((encoded.length % 4) > 0) {
            encoded += '='.repeat(4 - (encoded.length % 4));
          }
          this.value[index] = encoded
          this.querySelector("small[name=preview]").textContent = 
            encoded.length > 15 ? encoded.substring(0, 5) + "..." + encoded.substring(encoded.length - 5) : encoded
          const newev = new Event("input", { bubbles : true})
          this.dispatchEvent(newev)
        })
        reader.readAsDataURL(file)
      }
    })
  }

  content() {
    if (this.value.length <= 1) {
      const v = this.value.length ? this.value[0] : ''
      const preview = typeof(v) === "string" ? v.substring(0, 5) + "..." + v.substring(v.length - 5) : ""
      return `
        <input type="file" data-index="0" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required && !v ? 'required' : ''} value="${v}"/>
        <small name ="preview" class="form-text text-muted">${preview}</small>
      `
    }
    var out =
      this.value.map((c, i) => {
        const preview = typeof(v) === "string" ? c.substring(0, 5) + "..." + c.substring(v.length - 5) : ""
        return `
          <input type="file" data-index="${i}" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''} value="${c}"/>
          <small name ="preview" class="form-text text-muted">${preview}</small>
        `
      }).join("\n")
    return out
  }
}
window.customElements.define('d4s-ccp-input-file', CCPFileInputWidgetController);

class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController {

  #publicorprotected_dialog = null;
  #target = null
  #publiclink = null;
  #protectedlink = null;
  #index = null;

  constructor() {
    super()
  }

  async setPublicLink(l){
    const b = document.querySelector("d4s-boot-2")
    const link = await b.secureFetch(l)
    if(link.ok){
      const result = await link.json()
      this.#target.value = this.value[this.#index] = result
      this.#publicorprotected_dialog.style.display = "none"
      this.#publicorprotected_dialog.classList.remove("show")
      this.#publiclink = this.#protectedlink = this.#target =  this.#index = null
      const newev = new Event("input", { bubbles : true})
      this.dispatchEvent(newev)
    }else{
      alert("Unable to get public link for item")
      this.#target.value = this.value[this.#index] = ""
    }
  }

  addToolContent() {
    const iss = document.querySelector("d4s-boot-2").loginToken.iss;
    const addresses = {
      "https://accounts.dev.d4science.org/auth/realms/d4science": "https://workspace-repository.dev.d4science.org/storagehub/workspace",
      "https://accounts.pre.d4science.org/auth/realms/d4science": "https://pre.d4science.org/workspace",
      "https://accounts.d4science.org/auth/realms/d4science": "https://api.d4science.org/workspace"
    };
    this.rootdoc.querySelector("div[name=tools]").innerHTML += `
      <svg name="trigger" style="width:24;height:24;fill:#007bff; cursor:pointer" viewBox="0 -960 960 960">
          <path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h240l80 80h320q33 0 56.5 23.5T880-640H447l-80-80H160v480l96-320h684L837-217q-8 26-29.5 41.5T760-160H160Zm84-80h516l72-240H316l-72 240Zm0 0 72-240-72 240Zm-84-400v-80 80Z"/>
      </svg>
      <div name="ws" class="d-none position-absolute shadow border border-primary bg-light p-2" style="right:0;z-index:1000; line-height:1.5rem;overflow:hidden;padding:5px;">
        <div class="mb-1" style="border-bottom: solid 1px gray;">
          <div class="d-flex justify-content-between m-0">
            <h5 class="text-secondary m-0">Access your workspace</h5>
            <span class="btn text-danger p-0" style="font-weight:bold" name="closebtn">x</span>
          </div>
          <small class="text-muted m-0">Select an item or drag and drop it to a proper input</small>
        </div>
        <div style="min-width:350px; max-width:500px;overflow:auto;etxt-wrap:nowrap;text-overflow: ellipsis;min-height:5rem; max-height:10rem;">
          <d4s-storage-tree 
            base-url="${addresses[iss]}"
            file-download-enabled="true" 
            show-files="true"
            allow-drag="true"/>
        </div>
        <div class="d-flex justify-content-end mt-1 pt-1" style="border-top: solid 1px gray;">
          <span class="btn btn-primary" name="selectbtn">SELECT</span>
        </div>
      </div>
      <div class="modal fade" style="background-color:rgba(0,0,0,0.3)" name="publicorprotected" tabindex="-1" role="dialog">
        <div class="modal-dialog" role="document">
          <div class="modal-content shadow-lg border-primary">
            <div class="modal-body">
              Choose whether you want to use the public link or the protected link (requires authentication and authorization).
            </div>
            <div class="modal-footer">
              <span name="public" class="btn btn-info">Public link</span>
              <span name="protected" class="btn btn-primary">Protected link</span>
              <span name="cancel" class="btn btn-danger">Cancel</span>
            </div>
          </div>
        </div>
      </div>
    `
    this.#publicorprotected_dialog = this.rootdoc.querySelector("div.modal[name=publicorprotected]")
    this.#publicorprotected_dialog.addEventListener("click", ev => {
      ev.stopPropagation()
      ev.preventDefault()
      const name = ev.target.getAttribute("name")
      if(this.#index != null && this.#target != null){
        if(name === "public") {
          this.setPublicLink(this.#publiclink);
        }
        else if(name === "protected"){
          this.#target.value = this.value[this.#index] = this.#protectedlink;
          this.#publicorprotected_dialog.style.display = "none"
          this.#publicorprotected_dialog.classList.remove("show")
          this.#publiclink = this.#protectedlink = this.#target =  this.#index = null
          const newev = new Event("input", { bubbles : true})
          this.dispatchEvent(newev)
        }else{
          this.#publicorprotected_dialog.style.display = "none"
          this.#publicorprotected_dialog.classList.remove("show")
          this.#publiclink = this.#protectedlink = this.#target =  this.#index = null
        }
      }
    })

    const ws = this.rootdoc.querySelector("div[name=ws]")
    const st = ws.querySelector("d4s-storage-tree")
    this.addEventListener("click", ev=>{
      ev.stopPropagation()
      ev.preventDefault()
      if (ev.target.getAttribute("name") == "selectbtn") {
        this.#publicorprotected_dialog.style.display = "block"
        this.#publicorprotected_dialog.classList.add("show")
        this.#target = this.querySelector("input")
        this.#index = 0
        this.#publiclink = st.d4sWorkspace.getPublicLink(st.currentId)
        this.#protectedlink = st.d4sWorkspace.getDownloadLink(st.currentId)
      }
    })
    this.rootdoc.querySelector("svg[name=trigger]").addEventListener("click", ev => {
      ws.classList.toggle("d-none")
      ev.preventDefault()
      ev.stopPropagation()
    })

    this.rootdoc.querySelector("span[name=closebtn]").addEventListener("click", ev => {
      ws.classList.add("d-none")
      ev.preventDefault()
      ev.stopPropagation()
    })

    this.addEventListener("dragover", ev => {
      ev.preventDefault()
    })

    this.addEventListener("drop", ev => {
      ev.stopPropagation()
      if (ev.target.getAttribute("name") == this.name && ev.target.getAttribute("data-index") != null) {
        this.#publicorprotected_dialog.style.display = "block"
        this.#publicorprotected_dialog.classList.add("show")
        this.#target = ev.target
        this.#index = Number(ev.target.getAttribute("data-index"))
        this.#publiclink = ev.dataTransfer.getData("text/plain+publiclink")
        this.#protectedlink = ev.dataTransfer.getData("text/plain+downloadlink")
      }
    })

    this.addEventListener("input", ev => {
      ev.stopPropagation()
      if (ev.target.getAttribute("name") == this.name && ev.target.getAttribute("data-index") != null) {
        this.value[Number(ev.target.getAttribute("data-index"))] = ev.target.value
      }
    })

    document.addEventListener("keydown", ev => {
      if (ev.code == 'Escape') ws.classList.add("d-none");
    })
  }

  content() {
    if(!this.readonly && !this.querySelector("div[name=ws]")) this.addToolContent();
    if (this.value.length <= 1) {
      return `
       <input data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>`
    }
    var out =
      this.value.map((c, i) => {
        return `
          <input name="${this.name}" value="${c}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>
        `
      }).join("\n")
    return out
  }
}
window.customElements.define('d4s-ccp-input-remotefile', CCPRemoteFileInputWidgetController);

class CCPSecretInputWidgetController extends CCPBaseInputWidgetController {

  constructor() {
    super()
  }

  connectedCallback() {
    this.rootdoc.addEventListener("input", ev => {
      if (ev.target.getAttribute("name") === this.name) {
        const index = Number(ev.target.getAttribute("data-index"))
        this.value[index] = ev.target.value
      }
    })

    this.rootdoc.addEventListener("click", ev => {
      if (ev.target.getAttribute("name") === "password_toggle") {
        const index = Number(ev.target.getAttribute("data-index"))
        const field = this.rootdoc.querySelector(`input[data-index='${index}']`)
        if (field.type === "text") field.type = "password";
        else field.type = "text";
      }
    })
  }

  content() {
    if (this.value.length <= 1) {
      return `
        <div style="position:relative">
          <input data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" type="password" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>
          <span data-index="0" class="btn" style="position:absolute; right:0; bottom:0" name="password_toggle">&#128065;</span>
        </div>
        `
    }
    var out =
      this.value.map((c, i) => {
        return `
          <div style="position:relative">
            <input name="${this.name}" value="${c}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="password" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>
            <span data-index="${i}" class="btn" style="position:absolute; right:0; bottom:0" name="password_toggle">&#128065;</span>
          </div>
        `
      }).join("\n")
    return out
  }
}
window.customElements.define('d4s-ccp-input-secret', CCPSecretInputWidgetController);