class CCPInfrastructureList extends HTMLElement{
  
  #boot;
  #socket;
  #interval = null;
  #infrastructures;
  #rootdoc;
  
  #style = `
   <link rel="stylesheet" href="https://cdn.dev.d4science.org/ccp/css/common.css"></link>
   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"></link>
  <style>
    .ccp-infrastructure-list{
      list-style: none;
      padding-left: 1rem;
      user-select: none;
    }
    .ccp-infrastructure-item{
      padding: .3rem 0 .3rem 0;
    }
    .ccp-infrastructure-list .lxd{
      background-color: #dd4814;
    }
    .ccp-infrastructure-list .docker{
      background-color: #2496ed;
    }
  </style>
  `;
  
  #serviceurl; 
  #broadcasturl;
  
  constructor(){
    super()
    this.#boot = document.querySelector("d4s-boot-2")
    this.#serviceurl = this.getAttribute("serviceurl")
    this.#broadcasturl = this.getAttribute("broadcasturl")
    if(!this.#broadcasturl){
      this.#broadcasturl = this.#serviceurl.replace(/^http/, "ws")
    }
    this.#broadcasturl = this.#broadcasturl + "/ws/notification"
    this.#rootdoc = this.attachShadow({ "mode" : "open"})
  }

  connectedCallback(){
    this.connectBroadcast()
    this.fetchInfrastructures()  
  }

  fetchInfrastructures(){
    const prom1 = this.#boot.secureFetch(this.#serviceurl + "/infrastructures").
      then(resp=>{
        if(resp.status !== 200) throw "Unable to fetch infrastructures";
        return resp.json()
      }).then(data=>{
        this.#infrastructures = data
        this.showList()
      }).catch(err=>{
        alert(err)
      })
  }
  
  refreshInfrastructures(){
    this.#boot.secureFetch(this.#serviceurl + "/infrastructures", { method : "HEAD"})
  }
  
  showList(){
    if(this.getAttribute("render") !== "true") {
      this.#rootdoc.innerHTML = ""
      return;
    }
    this.#rootdoc.innerHTML = `
      <div class="ccp-infrastructure-controller">
        ${this.#style}
        <div class="card">
          <div class="card-header" style="padding:0.5rem">
            <div class="ccp-toolbar-header">
              <div>
                <span name="header" class="mr-2">Infrastructures</span>
              </div>
              <div class="ccp-toolbar-right ccp-infrastructure-toolbar">
                <button name="refresh" class="btn btn-primary ccp-toolbar-button" title="Refresh">
                  <svg viewBox="0 0 48 48"><path d="M24 40q-6.65 0-11.325-4.675Q8 30.65 8 24q0-6.65 4.675-11.325Q17.35 8 24 8q4.25 0 7.45 1.725T37 14.45V8h3v12.7H27.3v-3h8.4q-1.9-3-4.85-4.85Q27.9 11 24 11q-5.45 0-9.225 3.775Q11 18.55 11 24q0 5.45 3.775 9.225Q18.55 37 24 37q4.15 0 7.6-2.375 3.45-2.375 4.8-6.275h3.1q-1.45 5.25-5.75 8.45Q29.45 40 24 40Z"></path></svg>
                </button>
              </div>
            </div>
          </div>
          <div class="card-body">
            <ul class="ccp-infrastructure-list">
              ${this.showInfrastructures()}
            </ul>
          </div>
        </div>
      </div>      
    `
    this.#rootdoc.querySelector(".ccp-infrastructure-toolbar").addEventListener("click", ev=>{
      const evname = ev.target.getAttribute("name")
      switch(evname){
        case "refresh":
          this.refreshInfrastructures();
          break;
      }
    })
  }
  
  showInfrastructures(){
    return this.#infrastructures.map(i => {
      return `
        <li class="ccp-infrastructure-item" title="${i.description}">
          <details>
            <summary>
              <span>${i.name}</span>
              ${this.showAge(i)}
              ${this.showType(i)}
            </summary>
          </details>
        </li>
      `
    }).join("\n")
  }
  
  showAge(infra){
    const age = Math.floor(((new Date()) - (new Date(infra.date))) / 3600000)
    var cls = "badge-success"
    var agetext = "fresh"
    if(age > 24){
      cls = "badge-warning";
      agetext = "aged"
    } else if (age > 72){
      cls = "badge-secondary"
      agetext = "old"
    } 
    return `<span class="badge ${cls}" name="age" title="${age} hours">${agetext}</span>`
  }
  
  showType(infra){ 
    const t = infra.type.match(/docker/i) ? "docker" : null
    const t2 = !t && infra.type.match(/lxd/i) ? "lxd" : t
    return `<span class="badge badge-secondary ${t2}" title="${infra.type}">${infra.type}</span>`
  }
  
  connectBroadcast(){
    this.#socket = new WebSocket(this.#broadcasturl + "/infrastructures");
    this.#socket.onmessage = event=>{
      this.fetchInfrastructures()
    }
    this.#interval = window.setInterval( ()=>{
      if(this.#socket.readyState === 3){
        this.#socket.close()
        window.clearInterval(this.#interval)
        this.connectBroadcast() 
      }else{
        this.#socket.send("ping")  
      }
    }, 30000)
  }
}

window.customElements.define('d4s-ccp-infrastructurelist', CCPInfrastructureList);