class Utils {
  static elementFromString(string) {
    let tmpElement = document.createElement('div');
    tmpElement.innerHTML = string.trim();
    return tmpElement.firstChild;
  }

  static buildCorpusRequest(userId, corpusId) {
    return new Promise((resolve, reject) => {
      let corpus = app.data.users[userId].corpora[corpusId];

      fetch(`/corpora/${corpus.id}/build`, {method: 'POST', headers: {Accept: 'application/json'}})
        .then(
          (response) => {
            if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
            if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
            if (response.status === 409) {app.flash('Conflict', 'error'); reject(response);}
            app.flash(`Corpus "${corpus.title}" marked for building`, 'corpus');
            resolve(response);
          },
          (response) => {
            app.flash('Something went wrong', 'error');
            reject(response);
          }
        );
    });
  }

  static deleteCorpusRequest(userId, corpusId) {
    return new Promise((resolve, reject) => {
      let corpus = app.data.users[userId].corpora[corpusId];

      let modalElement = Utils.elementFromString(
        `
          <div class="modal">
            <div class="modal-content">
              <h4>Confirm Corpus deletion</h4>
              <p>Do you really want to delete the Corpus <b>${corpus.title}</b>? All files will be permanently deleted!</p>
            </div>
            <div class="modal-footer">
              <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
              <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
            </div>
          </div>
        `
      );
      document.querySelector('#modals').appendChild(modalElement);
      let modal = M.Modal.init(
        modalElement,
        {
          dismissible: false,
          onCloseEnd: () => {
            modal.destroy();
            modalElement.remove();
          }
        }
      );
      
      let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
      confirmElement.addEventListener('click', (event) => {
        let corpusTitle = corpus.title;
        fetch(`/corpora/${corpus.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
          .then(
            (response) => {
              if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
              if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
              app.flash(`Corpus "${corpus.title}" marked for deletion`, 'corpus');
              resolve(response);
            },
            (response) => {
              app.flash('Something went wrong', 'error');
              reject(response);
            }
          );
      });
      modal.open();
    });
  }

  static deleteCorpusFileRequest(userId, corpusId, corpusFileId) {
    return new Promise((resolve, reject) => {
      let corpus = app.data.users[userId].corpora[corpusId];
      let corpusFile = corpus.files[corpusFileId];

      let modalElement = Utils.elementFromString(
        `
          <div class="modal">
            <div class="modal-content">
              <h4>Confirm Corpus File deletion</h4>
              <p>Do you really want to delete the Corpus File <b>${corpusFile.title}</b>? All files will be permanently deleted!</p>
            </div>
            <div class="modal-footer">
              <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
              <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
            </div>
          </div>
        `
      );
      document.querySelector('#modals').appendChild(modalElement);
      let modal = M.Modal.init(
        modalElement,
        {
          dismissible: false,
          onCloseEnd: () => {
            modal.destroy();
            modalElement.remove();
          }
        }
      );

      let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
      confirmElement.addEventListener('click', (event) => {
        let corpusFileTitle = corpusFile.title;
        fetch(`/corpora/${corpusId}/files/${corpusFileId}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
          .then(
            (response) => {
              if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
              if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
              app.flash(`Corpus File "${corpusFileTitle}" deleted`, 'corpus');
              resolve(response);
            },
            (response) => {
              app.flash('Something went wrong', 'error');
              reject(response);
            }
          );
      });
      modal.open();
    });
  }

  static deleteSpaCyNLPPipelineModelRequest(userId, spaCyNLPPipelineModelId) {
    return new Promise((resolve, reject) => {
      let spaCyNLPPipelineModel = app.data.users[userId].spacy_nlp_pipeline_models[spaCyNLPPipelineModelId];
      let modalElement = Utils.elementFromString(
        `
          <div class="modal">
            <div class="modal-content">
              <h4>Confirm SpaCy NLP Pipeline Model deletion</h4>
              <p>Do you really want to delete the SpaCy NLP Pipeline Model <b>${spaCyNLPPipelineModel.title}</b>? All files will be permanently deleted!</p>
            </div>
            <div class="modal-footer">
              <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
              <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
            </div>
          </div>
        `
      );
      document.querySelector('#modals').appendChild(modalElement);
      let modal = M.Modal.init(
        modalElement,
        {
          dismissible: false,
          onCloseEnd: () => {
            modal.destroy();
            modalElement.remove();
          }
        }
      );
      let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
      confirmElement.addEventListener('click', (event) => {
        let spaCyNLPPipelineModelTitle = spaCyNLPPipelineModel.title;
        fetch(`/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModelId}`, {method: 'DELETE'})
          .then(
            (response) => {
              if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
              if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
              app.flash(`SpaCy NLP Pipeline Model "${spaCyNLPPipelineModelTitle}" marked for deletion`);
              resolve(response);
            },
            (response) => {
              app.flash('Something went wrong', 'error');
              reject(response);
            }
          );
      });
      modal.open();
    });
  }

  static deleteTesseractOCRPipelineModelRequest(userId, tesseractOCRPipelineModelId) {
    return new Promise((resolve, reject) => {
      let tesseractOCRPipelineModel = app.data.users[userId].tesseract_ocr_pipeline_models[tesseractOCRPipelineModelId];
      let modalElement = Utils.elementFromString(
        `
          <div class="modal">
            <div class="modal-content">
              <h4>Confirm Tesseract OCR Pipeline Model deletion</h4>
              <p>Do you really want to delete the Tesseract OCR Pipeline Model <b>${tesseractOCRPipelineModel.title}</b>? All files will be permanently deleted!</p>
            </div>
            <div class="modal-footer">
              <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
              <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
            </div>
          </div>
        `
      );
      document.querySelector('#modals').appendChild(modalElement);
      let modal = M.Modal.init(
        modalElement,
        {
          dismissible: false,
          onCloseEnd: () => {
            modal.destroy();
            modalElement.remove();
          }
        }
      );
      let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
      confirmElement.addEventListener('click', (event) => {
        let tesseractOCRPipelineModelTitle = tesseractOCRPipelineModel.title;
        fetch(`/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModelId}`, {method: 'DELETE'})
          .then(
            (response) => {
              if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
              if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
              app.flash(`Tesseract OCR Pipeline Model "${tesseractOCRPipelineModelTitle}" marked for deletion`);
              resolve(response);
            },
            (response) => {
              app.flash('Something went wrong', 'error');
              reject(response);
            }
          );
      });
      modal.open();
    });
  }

  static deleteJobRequest(userId, jobId) {
    return new Promise((resolve, reject) => {
      let job = app.data.users[userId].jobs[jobId];

      let modalElement = Utils.elementFromString(
        `
          <div class="modal">
            <div class="modal-content">
              <h4>Confirm Job deletion</h4>
              <p>Do you really want to delete the Job <b>${job.title}</b>? All files will be permanently deleted!</p>
            </div>
            <div class="modal-footer">
              <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
              <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
            </div>
          </div>
        `
      );
      document.querySelector('#modals').appendChild(modalElement);
      let modal = M.Modal.init(
        modalElement,
        {
          dismissible: false,
          onCloseEnd: () => {
            modal.destroy();
            modalElement.remove();
          }
        }
      );

      let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
      confirmElement.addEventListener('click', (event) => {
        let jobTitle = job.title;
        fetch(`/jobs/${job.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
          .then(
            (response) => {
              if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
              if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
              app.flash(`Job "${jobTitle}" marked for deletion`, 'job');
              resolve(response);
            },
            (response) => {
              app.flash('Something went wrong', 'error');
              reject(response);
            }
          );
      });
      modal.open();
    });
  }

  static getJobLogRequest(userId, jobId) {
    return new Promise((resolve, reject) => {
      let job = app.data.users[userId].jobs[jobId];

      fetch(`/jobs/${job.id}/log`, {method: 'GET', headers: {Accept: 'application/json, text/plain'}})
        .then(
          (response) => {
            if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
            if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
            return response.text();
          },
          (response) => {
            app.flash('Something went wrong', 'error');
            reject(response);
          }
        )
        .then(
          (text) => {
            let modalElement = Utils.elementFromString(
              `
                <div class="modal">
                  <div class="modal-content">
                    <h4>Job logs</h4>
                    <pre><code>${text}</code></pre>
                  </div>
                  <div class="modal-footer">
                    <a class="btn modal-close waves-effect waves-light">Close</a>
                  </div>
                </div>
              `
            );
            document.querySelector('#modals').appendChild(modalElement);
            let modal = M.Modal.init(
              modalElement,
              {
                onCloseEnd: () => {
                  modal.destroy();
                  modalElement.remove();
                }
              }
            );
            modal.open();
            resolve(text);
          }
        );
    });
  }

  static restartJobRequest(userId, jobId) {
    return new Promise((resolve, reject) => {
      let job = app.data.users[userId].jobs[jobId];

      let modalElement = Utils.elementFromString(
        `
          <div class="modal">
            <div class="modal-content">
              <h4>Confirm Job restart</h4>
              <p>Do you really want to restart the Job <b>${job.title}</b>? All Job Results will be permanently deleted.</p>
            </div>
            <div class="modal-footer">
              <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
              <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Restart</a>
            </div>
          </div>
        `
      );
      document.querySelector('#modals').appendChild(modalElement);
      let modal = M.Modal.init(
        modalElement,
        {
          dismissible: false,
          onCloseEnd: () => {
            modal.destroy();
            modalElement.remove();
          }
        }
      );

      let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
      confirmElement.addEventListener('click', (event) => {
        let jobTitle = job.title;
        fetch(`/jobs/${job.id}/restart`, {method: 'POST', headers: {Accept: 'application/json'}})
          .then(
            (response) => {
              if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
              if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
              if (response.status === 409) {app.flash('Conflict', 'error'); reject(response);}
              app.flash(`Job "${jobTitle}" restarted.`, 'job');
              resolve(response);
            },
            (response) => {
              app.flash('Something went wrong', 'error');
              reject(response);
            }
          );
      });
      modal.open();
    });
  }

  static deleteUserRequest(userId) {
    return new Promise((resolve, reject) => {
      let user = app.data.users[userId];

      let modalElement = Utils.elementFromString(
        `
          <div class="modal">
            <div class="modal-content">
              <h4>Confirm User deletion</h4>
              <p>Do you really want to delete the User <b>${user.username}</b>? All files will be permanently deleted!</p>
            </div>
            <div class="modal-footer">
              <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
              <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
            </div>
          </div>
        `
      );
      document.querySelector('#modals').appendChild(modalElement);
      let modal = M.Modal.init(
        modalElement,
        {
          dismissible: false,
          onCloseEnd: () => {
            modal.destroy();
            modalElement.remove();
          }
        }
      );

      let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
      confirmElement.addEventListener('click', (event) => {
        let userName = user.username;
        fetch(`/users/${user.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}})
          .then(
            (response) => {
              if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
              if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
              app.flash(`User "${userName}" marked for deletion`);
              resolve(response);
            },
            (response) => {
              app.flash('Something went wrong', 'error');
              reject(response);
            }
          );
      });
      modal.open();
    });
  }

  static shareTesseractOCRPipelineModelRequest(userId, tesseractOCRPipelineModelId, is_public) {
    return new Promise((resolve, reject) => {
      let tesseractOCRPipelineModel = app.data.users[userId].tesseract_ocr_pipeline_models[tesseractOCRPipelineModelId];
      let msg = '';
      if (is_public) {
        msg = `Model "${tesseractOCRPipelineModel.title}" is now public`;
      } else {
        msg = `Model "${tesseractOCRPipelineModel.title}" is now private`;
      }
      fetch(`/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModel.id}/toggle-public-status`, {method: 'POST', headers: {Accept: 'application/json'}})
      .then(
        (response) => {
          if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
          app.flash(msg);
          resolve(response);
        },
        (response) => {
          app.flash('Something went wrong', 'error');
          reject(response);
        }
      );
    });
  }

  static shareSpaCyNLPPipelineModelRequest(userId, spaCyNLPPipelineModelId, is_public) {
    return new Promise((resolve, reject) => {
      let spaCyNLPPipelineModel = app.data.users[userId].spacy_nlp_pipeline_models[spaCyNLPPipelineModelId];
      let msg = '';
      if (is_public) {
        msg = `Model "${spaCyNLPPipelineModel.title}" is now public`;
      } else {
        msg = `Model "${spaCyNLPPipelineModel.title}" is now private`;
      }
      fetch(`/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModel.id}/toggle-public-status`, {method: 'POST', headers: {Accept: 'application/json'}})
      .then(
        (response) => {
          if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
          app.flash(msg);
          resolve(response);
        },
        (response) => {
          app.flash('Something went wrong', 'error');
          reject(response);
        }
      );
    });
  }
}
