package com.d2v.web.comm;

import com.d2v.web.service.Doc2vecService;
import com.d2v.web.task.DocSimilarityMetaConfig;
import com.d2v.web.utils.SimpleDB;
import com.d2v.web.vo.*;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.print.Doc;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.sql.*;
import java.util.*;
import java.util.Date;

@RequestMapping("/api/d2v")
@RestController
public class HomeRestController {

    private static final Logger log = LoggerFactory.getLogger(HomeRestController.class);

    @Autowired
    Doc2vecService doc2vecService;

    @RequestMapping("/dbConnect")
    public Boolean dbConnect(@RequestBody DBConnectVO dbConnectVO) {
        return doc2vecService.initlizeDBSetting(dbConnectVO);
    }

    @RequestMapping("/dbConnectJurl")
    public Boolean dbConnect(String jUrl) {
        return doc2vecService.initlizeDBSetting(jUrl);
    }

    @RequestMapping("/w2vStart")
    public void w2vStart(@RequestParam(value="jUrl") String jUrl) throws IOException {
        if (jUrl.equals("")) {
            jUrl = DocSimilarityMetaConfig.JURL;
        }
        try {
            doc2vecService.initlizeDBSetting(jUrl);
        }
        catch (Exception e){

        }
        DocSimilarityMetaConfig.state = "LOADING";
        DocSimilarityMetaConfig.step = "W2V";
        DocSimilarityMetaConfig.START_TIME = new Date();
        try {
            doc2vecService.extractInputFileDoc();
        }
        catch(Exception e) {
            DocSimilarityMetaConfig.ERROR_MESSAGE = "extractInputFile Error...";
            log.info("extractInputFile Error...");
            DocSimilarityMetaConfig.exceptions.add("extractInputFile Error");
            DocSimilarityMetaConfig.state = "ERROR";
            DocSimilarityMetaConfig.CODE = 400;
            DocSimilarityMetaConfig.END_TIME = new Date();
            return;
        }
        try {
            doc2vecService.training();
        }
        catch(Exception e) {
            log.info("W2v Error...");
            DocSimilarityMetaConfig.exceptions.add("W2v Error");
            DocSimilarityMetaConfig.END_TIME = new Date();
            DocSimilarityMetaConfig.CODE = 400;
            return ;
        }
        DocSimilarityMetaConfig.state = "COMPLETE";
        DocSimilarityMetaConfig.END_TIME = new Date();
    }

    @RequestMapping("/d2vStart")
    public void d2vStart(@RequestBody SettingVO settingVO) throws IOException {
        if (settingVO.getjUrl().equals("")) {
            settingVO.setjUrl(DocSimilarityMetaConfig.JURL);
        }
        doc2vecService.initlizeDBSetting(settingVO.getjUrl());
        DocSimilarityMetaConfig.state = "LOADING";
        DocSimilarityMetaConfig.step = "D2V";
        DocSimilarityMetaConfig.START_TIME = new Date();
        DocSimilarityMetaConfig.WORKING_COUNT.set(0);
        try {
            doc2vecService.execute(settingVO);
        }
        catch(Exception e) {
            log.info("D2v Error...");
            DocSimilarityMetaConfig.exceptions.add("D2v Error");
            DocSimilarityMetaConfig.state = "ERROR";
            DocSimilarityMetaConfig.END_TIME = new Date();
            DocSimilarityMetaConfig.CODE = 400;
            return ;
        }
        DocSimilarityMetaConfig.state = "COMPLETE";
        DocSimilarityMetaConfig.END_TIME = new Date();
    }

    @RequestMapping("/d2vProgress")
    public List<String> d2vProgress() {
        List<String> list = new ArrayList<>();
        list.add(String.valueOf(DocSimilarityMetaConfig.WORKING_COUNT.get()));
        list.add(String.valueOf(DocSimilarityMetaConfig.SOURCE_DATA_SIZE));
        list.add(DocSimilarityMetaConfig.ERROR_MESSAGE);
        return list;

    }

    @RequestMapping("/progress")
    public Doc2vecProgressVO progress() {
        Doc2vecProgressVO doc2vecProgressVO = new Doc2vecProgressVO();
        doc2vecProgressVO.setCode(DocSimilarityMetaConfig.CODE);
        doc2vecProgressVO.setState(DocSimilarityMetaConfig.state);
        doc2vecProgressVO.setStep(DocSimilarityMetaConfig.step);
        Doc2vecTaskInfo doc2vecTaskInfo = new Doc2vecTaskInfo();
        doc2vecTaskInfo.setStartTime(DocSimilarityMetaConfig.START_TIME);
        doc2vecTaskInfo.setEndTime(DocSimilarityMetaConfig.END_TIME);
        doc2vecTaskInfo.setExceptions(DocSimilarityMetaConfig.exceptions);
        doc2vecTaskInfo.setNowDataSize(DocSimilarityMetaConfig.WORKING_COUNT.get());
        doc2vecTaskInfo.setTotalDataSize(DocSimilarityMetaConfig.SOURCE_DATA_SIZE);
        doc2vecTaskInfo.setPrevVer(DocSimilarityMetaConfig.prevVer);
        doc2vecTaskInfo.setProcVer(DocSimilarityMetaConfig.procVer);
        doc2vecTaskInfo.setSourceDomain(DocSimilarityMetaConfig.SOURCE_DOMAIN);
        doc2vecProgressVO.setDoc2vecTaskInfo(doc2vecTaskInfo);
        return doc2vecProgressVO;
    }

    @RequestMapping(value = "/checkDBConnection", produces = "application/text; charset=utf-8", method = RequestMethod.POST)
    public String dbChecker(
            @RequestParam(value = "ipUrl", required = false) String ipUrl,
            @RequestParam(value = "portNumber", required = false) String portNumber,
            @RequestParam(value = "dbName", required = false) String dbName,
            @RequestParam(value = "dbID", required = false) String dbID,
            @RequestParam(value = "dbPasswd", required = false) String dbPasswd,
            Locale locale,
            Model model,
            HttpSession hSession) {

        String result = "정상 연결되었습니다.";
        //////////////////////////////////////
        Connection connection = null;
        Statement st = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:mysql://"+ipUrl+":"+portNumber+"/"+dbName,
                    dbID,
                    dbPasswd);
            connection.close();
        }
        catch (Exception e)
        {
            result = "Database 연결에 실패하였습니다.";
            e.printStackTrace();
        }

    //////////////////////////////////////

        model.addAttribute("content", result);

        return result;
    }

    @RequestMapping(value = "/getDBTables", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> getDBTables(
            @RequestParam(value = "ipUrl", required = false) String ipUrl,
            @RequestParam(value = "portNumber", required = false) String portNumber,
            @RequestParam(value = "dbName", required = false) String dbName,
            @RequestParam(value = "dbID", required = false) String dbID,
            @RequestParam(value = "dbPasswd", required = false) String dbPasswd,
            Locale locale,
            Model model,
            HttpSession hSession) {
        Map<String, Object> jsonObject = new HashMap<String, Object>();

        Connection connection = null;
        Statement st = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:mysql://"+ipUrl+":"+portNumber+"/"+dbName,
                    dbID,
                    dbPasswd);

            DatabaseMetaData md = connection.getMetaData();
            ResultSet tableRSet = md.getTables(dbName, null, "%", null);
            TreeMap<String, Object> tableMap = new TreeMap<>();
            while (tableRSet.next()) {

                List<String> colList = new ArrayList<>();
                ResultSet colRSet = md.getColumns(dbName, null, tableRSet.getString(3), "%");
                while (colRSet.next()) {
                    colList.add(colRSet.getString(4));
                }
                tableMap.put(tableRSet.getString(3),colList);
            }
            jsonObject.put("tables",tableMap);
            connection.close();
        }
        catch (Exception e)
        {
            jsonObject.put("error","Database 연결에 실패하였습니다.");
            e.printStackTrace();
            return jsonObject;
        }

        return jsonObject;
    }
}
