class CCPInputWidgetController extends HTMLElement {
  
  #input = null;
  #renderer = null;
  
  constructor(){
    super()
    this.#input = JSON.parse(this.getAttribute("input"))
    this.#renderer = Renderer.instance(this.#input)
  }
  
  connectedCallback(){
    console.log("Widget connected")
    this.innerHTML = this.render()
    this.#renderer.connectedCallback(this)
  }
  
  render(){
    return this.#renderer.render()
  }
  
  get name(){
    return this.#renderer.name
  }
  
  get value(){
    return this.#renderer.getValue(this)
  }
}
window.customElements.define('d4s-ccp-input', CCPInputWidgetController);

class Renderer{
  
  #input = null;
  
  constructor(input){
    this.#input = input 
  }
  
  connectedCallback(controller){
    
  }
  
  get schema(){
    return this.#input.schema
  }
  
  get name(){
    return this.#input.id
  } 
  
  get title(){
    return this.#input.title
  }
  
  get description(){
    return this.#input.description
  }
  
  get required(){
    return this.#input.minOccurs > 0
  }
  
  static instance(input){
    if(this.isEnum(input)){
      return new EnumInputRenderer(input)
    }
    if(this.isCode(input)){
      return new CodeInputRenderer(input)
    }
    if(this.isDateTime(input)){
      return new DateTimeInputRenderer(input)
    }
    return new SimpleInputRenderer(input)
  }
  
  static isEnum(input){
    return (input.schema.type === "string") && ("enum" in input.schema) 
  }
  
  static isCode(input){
    return (input.schema.type === "string") && 
      ("format" in input.schema) && 
      (input.schema.format != null) && 
      (input.schema.format.toLowerCase() === "code") 
  }
  
  static isDateTime(input){
    return (input.schema.type === "string") && 
      ("format" in input.schema) &&
      (input.schema.format != null) &&
      (["date", "time", "datetime"].indexOf(input.schema.format.toLowerCase()) !== -1) 
  }
}

class SimpleInputRenderer extends Renderer{
  
  #html = null;
  
  constructor(input){
    super(input)
  }
  
  getValue(parent){
    return parent.querySelector("input").value
  }
  
  render(){
    let required = this.required ? 'required="required"' : "" 
    let readonly = this.readOnly ? 'readonly="readOnly"' : ""
    this.#html = `
      <div class="ccp-input-widget form-field">
        <label>
          ${this.title}
          <span class="ccp-help-icon" title="${this.description}" alt="${this.description}">?</span>
        </label>
        <input class="ccp-input-widget form-control" name="${this.name}" value="${this.schema.default}" ${required} ${readonly}></input>
      </div>
    `  
    return this.#html
  }
}

class DateTimeInputRenderer extends Renderer{
  
  #html = null;
  
  constructor(input){
    super(input)
  }
  
  getValue(parent){
    return parent.querySelector("input").value
  }
  
  render(){
    let required = this.required ? 'required="required"' : "" 
    let readonly = this.schema.readOnly ? 'readonly="readOnly"' : ""
    let t = this.schema.format.toLowerCase() === "datetime" ? "datetime-local" : this.schema.format.toLowerCase()
    this.#html = `
      <div class="ccp-input-widget form-field">
        <label>
          ${this.title}
          <span class="ccp-help-icon" title="${this.description}" alt="${this.description}">?</span>
        </label>
        <input type="${t}" class="ccp-input-widget form-control" name="${this.name}" value="${this.schema.default}" ${required} ${readonly}></input>
      </div>
    `  
    return this.#html
  }
}

class EnumInputRenderer extends Renderer{
  
  #html = null;
  
  constructor(input){
    super(input)
  }
  
  getValue(parent){
    return parent.querySelector("select").value
  }
  
  render(){
    let options = this.schema.enum.map(e => {
      return e === this.schema.default ? 
        `<option name="${e}" value="${e}" selected="selected">${e}</option>` :
        `<option name="${e}" value="${e}">${e}</option>`
    })
    let required = this.required ? 'required="required"' : ""
    let readonly = this.schema.readOnly ? 'readonly="readOnly"' : ""
    this.#html = `
      <div class="ccp-input-widget form-field">
        <label>
          ${this.title}
          <span class="ccp-help-icon" title="${this.description}" alt="${this.description}">?</span>
        </label>
        <select class="ccp-input-widget form-control" name="${this.name}" value="${this.schema.default}" ${required}>
          ${options.join("")}
        </select>
      </div>
    `
    return this.#html
  }
}

class CodeInputRenderer extends Renderer{
  
  #html = null;
  #codemirror = null;
  
  constructor(input){
    super(input)
  }
  
  getValue(parent){
    return parent.querySelector("textarea").textContent
  }
  
  connectedCallback(controller){
    /*const ta = controller.querySelector("textarea")
    const opts = { 
      lineNumbers: true,
      indentUnit: 4,
      matchBrackets: true,
      mode: this.schema.contentMediaType,
      readOnly : this.schema.readOnly ? true : false
    }
    
    this.#codemirror = CodeMirror.fromTextArea(ta, opts)
    this.#codemirror.setValue(this.schema.default)
    this.#codemirror.refresh()*/
  }
  
  render(){
    let required = this.required ? 'required="required"' : ""
    let readonly = this.schema.readOnly ? 'readonly="readOnly"' : ""
    this.#html = `
      <div class="ccp-input-widget form-field">
        <label>
          ${this.title}
          <span class="ccp-help-icon" title="${this.description}" alt="${this.description}">?</span>
        </label>
        <textarea class="ccp-input-widget form-control" ${required} ${readonly}>${this.schema.default}</textarea>
      </div>
    `
    return this.#html
  }
}
