class CorpusAnalysisClient {
  constructor(corpusId, socket) {
    this.callbacks = {};
    this.corpusId = corpusId;
    this.displays = {};
    this.socket = socket;

    // socket on event for corpous analysis initialization
    socket.on("corpus_analysis_init", (response) => {
      let errorText;

      if (response.code === 200) {
        console.log(`corpus_analysis_init: ${response.code} - ${response.msg}`);
        if (this.callbacks.init != undefined) {
          this.callbacks.init(response.payload);
          this.callbacks.get_metadata();  // should hold the function getMetaData
        }
        if (this.displays.init != undefined) {
          this.displays.init.setVisibilityByStatus("success");
        }
      } else {
        errorText = `Error ${response.code} - ${response.msg}`;
        if (this.displays.init.errorContainer != undefined)  {
          this.displays.init.errorContainer.innerHTML = `<p class="red-text">` +
                   `<i class="material-icons tiny">error</i> ${errorText}</p>`;
        }
        if (this.displays.init != undefined)  {
          this.displays.init.setVisibilityByStatus("error");
        }
        console.error(`corpus_analysis_init: ${errorText}`);
      }
    });

    // socket on event for recieving meta
    socket.on('corpus_analysis_send_meta_data', (response) => {
      let errorText;

      if (response.code === 200) {
        console.log(`corpus_analysis_send_meta_data: ${response.code} - ${response.msg} - ${response.desc}`);
        if (this.callbacks.recv_meta_data != undefined) {
          this.callbacks.recv_meta_data(response.payload);
        }
      } else {
        errorText = `Error ${response.code} - ${response.msg}`;
        if (this.displays.init.errorContainer != undefined)  {
          this.displays.init.errorContainer.innerHTML = `<p class="red-text">` +
                   `<i class="material-icons tiny">error</i> ${errorText}</p>`;
        }
        if (this.displays.init != undefined)  {
          this.displays.init.setVisibilityByStatus("error");
        }
        console.error(`corpus_analysis_send_meta_data: ${errorText}`);
      }
    });

    // socket on event for recieveing query results
    socket.on("corpus_analysis_query", (response) => {
      let errorText;

      if (response.code === 200) {
        console.log(`corpus_analysis_query: ${response.code} - ${response.msg}`);
        if (this.callbacks.query != undefined)  {
          this.callbacks.query(response.payload);
        }
        if (this.displays.query != undefined)  {
          this.displays.query.setVisibilityByStatus("success");
        }
      } else {
        errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
        nopaque.flash(errorText, "error");
        if (this.displays.query.errorContainer != undefined)  {
          this.displays.query.errorContainer.innerHTML = `<p class="red-text">`+
                    `<i class="material-icons tiny">error</i> ${errorText}</p>`;
        }
        if (this.displays.query != undefined)  {
          this.displays.query.setVisibilityByStatus("error");
        }
        console.error(`corpus_analysis_query: ${errorText}`);
      }
    });


    socket.on("corpus_analysis_query_results", (response) => {
        if (this.callbacks.query_results != undefined) {
          this.callbacks.query_results(response.payload);
        }
    });

    socket.on("corpus_analysis_inspect_match", (response) => {
      if (this.callbacks.query_match_context != undefined) {
        this.callbacks.query_match_context(response);
      }
    });
  }

  init() {
    if (this.displays.init.errorContainer != undefined)  {
      this.displays.init.errorContainer.innerHTML == "";
    }
    if (this.displays.init != undefined)  {
      this.displays.init.setVisibilityByStatus("waiting");
    }
    this.socket.emit("corpus_analysis_init", this.corpusId);
  }

  getMetaData() {
    // just emits thos to tell the server to gather all meta dat infos and send
    // those back
    this.socket.emit("corpus_analysis_get_meta_data", this.corpusId);
  }

  query(queryStr) {
    let displayOptionsData;
    let resultListOptions;

    if (this.displays.query.errorContainer != undefined)  {
      this.displays.query.errorContainer.innerHTML == "";
    }
    if (this.displays.query != undefined)  {
      this.displays.query.setVisibilityByStatus("waiting");
    }
    nopaque.socket.emit("corpus_analysis_query", queryStr);
  }

  setCallback(type, callback) {
    // saves callback functions into an object. Key is function type, callback
    // is the callback function
    this.callbacks[type] = callback;
  }

  setDisplay(type, display) {
    this.displays[type] = display;
  }
}


class CorpusAnalysisDisplay {
  constructor(element) {
    this.element = element;
    this.errorContainer = element.querySelector(".error-container");
    this.showOnError = element.querySelectorAll(".show-on-error");
    this.showOnSuccess = element.querySelectorAll(".show-on-success");
    this.showWhileWaiting = element.querySelectorAll(".show-while-waiting");
    this.hideOnComplete = element.querySelectorAll(".hide-on-complete")
  }

  setVisibilityByStatus(status) {
    switch (status) {
      case "error":
        for (let element of this.showOnError) {
          element.classList.remove("hide");
        }
        for (let element of this.showOnSuccess) {
          element.classList.add("hide");
        }
        for (let element of this.showWhileWaiting) {
          element.classList.add("hide");
        }
        break;
      case "success":
        for (let element of this.showOnError) {
          element.classList.add("hide");

        }
        for (let element of this.showOnSuccess) {
          element.classList.remove("hide");
        }
        for (let element of this.showWhileWaiting) {
          element.classList.add("hide");
        }
        break;
      case "waiting":
        for (let element of this.showOnError) {
          element.classList.add("hide");
        }
        for (let element of this.showOnSuccess) {
          element.classList.add("hide");
        }
        for (let element of this.showWhileWaiting) {
          element.classList.remove("hide");
        }
        break;
      default:
        // Hide all
        for (let element of this.showOnError) {
          element.classList.add("hide");
        }
        for (let element of this.showOnSuccess) {
          element.classList.add("hide");
        }
        for (let element of this.showWhileWaiting) {
          element.classList.add("hide");
        }
    }
  }
}