import LoadTester from './components/LoadTester';
import LoadTestResult from './components/LoadTestResult';

class LoadTestManagerModel {
  constructor() {
    this.testList = [];
    this.scenarios = [];
  }

  getTestList() {
    return this.testList;
  }

  getScenarioList() {
    return this.scenarios;
  }
}

class LoadTestManagerView {
  constructor(model, controller) {
    this.model = model;
    this.controller = controller;
  }

  render(element) {
    this.element = element;
    this.element.innerHTML = `<div></div>`;
  }

  testListTemplate(test) {
    return `
        <li class="d-flex justify-content-between " data-id="${test.id}">
            <a href="#" class="d-inline-flex align-items-center rounded open_load_test">${test.name}</a>
            <div class="d-flex justify-content-between">
                <button class="p-1 reset-button delete_load_test"><i class="fa fa-trash-can"></i></button>
            </div>
        </li>
        `;
  }

  renderTestList() {
    const testList = this.model.getTestList();
    let testListHtml = testList.map((test) => this.testListTemplate(test)).join('');
    $('.load_test_list').html(testListHtml);
    let nodes = document.querySelectorAll('.load_test_list li');
    nodes.forEach((node) => {
      if (this.controller.currentTest !== null && $(node).data('id') === this.controller.currentTest.id) {
        node.classList.add('selected');
      }
    });
  }
}

class LoadTestManagerController {
  constructor(contextPath, model, testResult) {
    this.contextPath = contextPath;
    this.model = model;
    this.view = new LoadTestManagerView(this.model, this);
    this.testResult = testResult;
  }

  async init(element) {
    console.log('LoadTestManagerController.init() called');
    await this.loadScenarioList();
    this.currentTest = new LoadTester(this.contextPath, this.model.scenarios);
    this.currentTest.init(document.getElementById('load-tester-view'));
    this.view.render(element);
    this.bindEvents();
    await this.loadTestList();
  }

  showLoadingOverlay() {
    $('#loading-overlay').show();
  }

  hideLoadingOverlay() {
    $('#loading-overlay').hide();
  }

  getLoadTestListURL() {
    return this.contextPath + 'mgmt/load_test/list.do';
  }

  getLoadTestCreateURL() {
    return this.contextPath + 'mgmt/load_test/create.do';
  }

  getLoadTestUpdateURL() {
    return this.contextPath + 'mgmt/load_test/update.do';
  }

  getLoadTestDeleteURL() {
    return this.contextPath + 'mgmt/load_test/delete.do';
  }

  openTest(event) {
    console.log('openTest');
    let testId = $(event.target).closest('li').data('id');
    document.querySelectorAll('.load_test_list li').forEach((node) => {
      node.classList.remove('selected');
    });
    document.querySelector(`.load_test_list li[data-id="${testId}"]`).classList.add('selected');

    let currentTestModel = this.model.getTestList().find((test) => test.id === testId);
    this.currentTest.openLoadTest(currentTestModel);
    this.testResult.showResult(testId);
  }

  showNewTestModal() {
    $('#new_load_test_modal').find('input').val('');
    $('#new_load_test_modal').modal('show');
  }

  showDeleteModal(event) {
    const id = $(event.currentTarget).closest('li').data('id');
    $('#confirm_delete_modal').find('.confirm_delete_load_test').data('id', id);
    $('#confirm_delete_modal').modal('show');
  }

  async loadTestList(callback) {
    this.showLoadingOverlay();
    const response = await fetch(this.getLoadTestListURL(), {
      method: 'GET', headers: {
        'Content-Type': 'application/json', 'X-XSRF-TOKEN': $('meta[name="_csrf"]').attr('content')
      }
    });
    this.model.testList = await response.json();
    this.view.renderTestList();
    this.hideLoadingOverlay();
  }

  async loadScenarioList() {
    const response = await fetch(this.contextPath + 'mgmt/api_scenario/list.do', {
      method: 'GET', headers: {
        'Content-Type': 'application/json', 'X-XSRF-TOKEN': $('meta[name="_csrf"]').attr('content')
      }
    });
    this.model.scenarios = await response.json();
  }

  createLoadTest() {
    const testName = $('#new_load_test_modal').find('input').val();
    if (testName) {
      const me = this;
      me.showLoadingOverlay();
      this.currentAjaxRequest = $.ajax({
        url: this.getLoadTestCreateURL(),
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({name: testName}),
        success: function(data) {
          me.loadTestList(() => {
          });
        },
        error: function(response, textStatus, errorThrown) {
          me.hideLoadingOverlay();
          $('.toast-body').text(response.responseJSON.error);
          $('.toast').toast('show');
        },
        complete: function() {
          me.hideLoadingOverlay();
          $('#new_load_test_modal').modal('hide');
        }
      });
    }
  }

  saveLoadTest() {
    if (this.currentTest !== null) {

      const me = this;
      me.showLoadingOverlay();
      this.currentAjaxRequest = $.ajax({
        url: this.getLoadTestUpdateURL(),
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify(this.currentTest.getLoadTest()),
        error: function(response, textStatus, errorThrown) {
          me.hideLoadingOverlay();
          $('.toast-body').text(response.responseJSON.error);
          $('.toast').toast('show');
        },
        complete: function() {
          me.hideLoadingOverlay();
          $('.toast-body').text('저장되었습니다.');
          $('.toast').toast('show');
        }
      });
    }
  }

  removeLoadTest(event) {
    const id = $(event.currentTarget).data('id');
    const me = this;
    me.showLoadingOverlay();
    this.currentAjaxRequest = $.ajax({
      url: this.getLoadTestDeleteURL(),
      type: 'POST',
      contentType: 'application/json',
      data: JSON.stringify({id: id}),
      error: function(response, textStatus, errorThrown) {
        me.hideLoadingOverlay();
        $('.toast-body').text(response.responseJSON.error);
        $('.toast').toast('show');
      },
      complete: function() {
        me.hideLoadingOverlay();
        $('#confirm_delete_modal').modal('hide');
        $('.toast-body').text('삭제되었습니다.');
        $('.toast').toast('show');
        me.loadTestList(() => {
          if (me.model.getTestList().length > 0) {
            //me.openT(me.getScenarioList()[0].id);
          }
        });
      }
    });
  }

  resetLoadTest() {
    this.testResult.reset();
  }

  showTestReport() {
    this.testResult.showTestRpeort();
  }

  bindEvents() {
    const events = [
      {type: 'click', selector: '#new_load_test', action: this.showNewTestModal.bind(this)},
      {type: 'click', selector: '.create_load_test', action: this.createLoadTest.bind(this)},
      {type: 'click', selector: '.save_load_test', action: this.saveLoadTest.bind(this)},
      {type: 'click', selector: '.reset_load_test', action: this.resetLoadTest.bind(this)},
      {type: 'click', selector: '.show_test_report', action: this.showTestReport.bind(this)},
      {type: 'click', selector: '.delete_load_test', action: this.showDeleteModal.bind(this)},
      {type: 'click', selector: '.open_load_test', action: this.openTest.bind(this)},
      {type: 'click', selector: '.confirm_delete_load_test', action: this.removeLoadTest.bind(this)}];

    for (let event of events) {
      $(document).on(event.type, event.selector, event.action);
    }
  }
}

class LoadTestManager {
  constructor(contextPath) {
    this.contextPath = contextPath;
    this.model = new LoadTestManagerModel();
    this.testResult = new LoadTestResult(this.contextPath, document.getElementById('load-tester-result-view'));
    this.testResult.init();
    this.controller = new LoadTestManagerController(this.contextPath, this.model, this.testResult);
  }

  init() {
    console.log('LoadTestManager.init() called');
    let element = document.getElementById('load_test_menubar');
    this.controller.init(element);
  }
}

export default LoadTestManager;
