import line_i18n from 'line-i18n'
import { IVProgProcessor } from "./../processor/ivprogProcessor";
import { DOMConsole} from "./../io/domConsole";
import * as LocalizedStringsService from "../services/localizedStringsService";
import { OutputMatching } from './output_matching/output_matching';


const LocalizedStrings = LocalizedStringsService.getInstance();

const StringTypes = line_i18n.StringTypes;

export class IVProgAssessment {

  constructor (ast_code, testCases, domConsole) {
    this.ast_code = ast_code;
    this.testCases = testCases;
    this.domConsole = domConsole;
  }

  runTest () {
    const outerRef = this;
    try {
      // loop test cases and show messages through domconsole
      const partialTests = this.testCases.map( (t, name) => {
        return new OutputMatching(new IVProgProcessor(outerRef.ast_code), t.input, t.output, name);
      });
      const testResult = partialTests.map(om => om.eval());
      return Promise.all(testResult).then(results => {
        let grade = 0;
        for(let i = 0; i < results.length; ++i) {
          const result = results[i];
          grade += result.grade;
          if(result.grade == 1) {
            outerRef.writeToConsole(DOMConsole.INFO, StringTypes.MESSAGE,'test_case_success',
              result.name + 1, result.generateOutput());
          } else if (result.status == 1) {
            outerRef.writeToConsole(DOMConsole.ERR, StringTypes.ERROR,'test_case_failed_exception',
              result.name + 1, result.error_msg, result.generateOutput());
          } else {
            outerRef.writeToConsole(DOMConsole.ERR, StringTypes.ERROR,'test_case_failed',
              result.name + 1, result.generateOutput());
          }
        }
        grade /= results.length;
        const channel = grade == 1 ? DOMConsole.INFO : DOMConsole.ERR;
        outerRef.writeToConsole(channel, StringTypes.MESSAGE, "test_suite_grade", (grade * 100).toFixed(2));
        return grade;
      });
      // return testResult.then(function (total) {
      //   const grade = total / outerRef.testCases.length;
      //   const channel = grade == 1 ? DOMConsole.INFO : DOMConsole.ERR;
      //   outerRef.writeToConsole(channel, StringTypes.MESSAGE, "test_suite_grade", (grade * 100).toFixed(2));
      //   return Promise.resolve(grade)
      // }).catch(err => {
      //   outerRef.domConsole.err("Erro inesperado durante o cálculo da nota.");// try and show error messages through domconsole
      //   outerRef.domConsole.err(err.message);
      //   return Promise.resolve(0);
      // });
    } catch (error) {
      outerRef.domConsole.err("Erro inesperado durante a execução do programa");// try and show error messages through domconsole
      outerRef.domConsole.err(error.message);
      return Promise.resolve(0);
    }
  }

  showErrorMessage (errorID, ...args) {
    this.domConsole.err(LocalizedStrings.getError(errorID, args));
  }

  showInfoMessage (msgID, ...args) {
    this.domConsole.info(LocalizedStrings.getMessage(msgID, args));
  }

  writeToConsole (channel, msgType, msgID, ...args) {
    let msg = LocalizedStrings.getString(msgID, msgType);
    msg = LocalizedStrings.processString(msg, args);
    switch(channel) {
      case DOMConsole.ERR: {
        this.domConsole.err(msg);
        break;
      }
      case DOMConsole.INFO: {
        this.domConsole.info(msg);
        break;
      }
      case DOMConsole.USER: {
        this.domConsole.write(msg);
        break;
      }
    }
  }
}