package net.northking.cctp.daemon.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.northking.cctp.commands.win.TaskKill;
import net.northking.cctp.daemon.config.DaemonProperties;
import net.northking.cctp.daemon.config.EngineProperties;
import net.northking.cctp.daemon.entity.ResultWrapper;
import net.northking.cctp.se.dto.ScriptEngineInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.web.client.RestTemplate;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class ScriptEngineProcess extends AppLifecycle
{

  private static final Logger logger = LoggerFactory.getLogger(ScriptEngineProcess.class);

  private ObjectMapper objectMapper = new ObjectMapper();


  /**
   * 配置参数
   */
  private final DaemonProperties daemonProperties;
  private final EngineProperties engineProperties;

  private final RestTemplate restTemplate;

  private final DaemonService daemonService;

  private String PID;


  public ScriptEngineProcess(DaemonProperties daemonProperties, RestTemplate restTemplate, DaemonService daemonService)
  {
    this.daemonProperties = daemonProperties;
    this.engineProperties = daemonProperties.getEngine();
    this.restTemplate = restTemplate;
    this.daemonService = daemonService;
  }


  @Override
  public boolean isStarted()
  {
    String pid = getPid();

    if (pid == null || "".equals(pid.trim()))
    {
      return false;
    }
    return findProcessByPid(pid).size() > 0;
  }

  @Override
  public void start()
  {
    if(daemonService.startCheck()){
    startOnWindows();
  }
  }

  private void startOnWindows()
  {
    //异步线程启动并持续打印数据
    EngineServiceStartThread thread = new EngineServiceStartThread(daemonProperties,daemonService);
    thread.start();
    daemonService.restartEngineFinish();
  }

  @Override
  public void stop()
  {
    if (!stopByHTTP())
    {
      shutdown();
    }
  }

  private boolean stopByHTTP()
  {
    String stopUrl = "http://localhost:" + engineProperties.getPort() + "/v1/stop";
    Map<String, String> uriVariables = new HashMap<>();
    String body = "";
    HttpHeaders headers = new HttpHeaders();
    // TODO 设置HTTP请求头
    HttpEntity<String> request = new HttpEntity(uriVariables, headers);
    try {
      String responseBody = restTemplate.postForObject(stopUrl, request, String.class, uriVariables);
    }catch (Exception e){
      logger.debug("通过HTTP接口停止脚本引擎 无法停止原因："+e.getMessage());
      logger.debug("判定进程无法使用转为强制重启 --------");
      return false;
    }
    // TODO 处理应答结果
    logger.debug("通过HTTP接口停止脚本引擎成功");
    return true;
  }


  @Override
  public void restart()
  {
    stop();
    start();
  }

  @Override
  public boolean alive()
  {
    String infoUrl = "http://localhost:" + engineProperties.getPort() + "/v1/info";
    Map<String, String> uriVariables = new HashMap<>();

    try
    {
      logger.debug("获取脚本引擎信息，请求接口：HTTP GET {}", infoUrl);
      String responseBody = restTemplate.getForObject(infoUrl, String.class, uriVariables);
      logger.debug("收到脚本引擎信息报文：{}", responseBody);

      ResultWrapper<ScriptEngineInfo> wrapper = objectMapper.readValue(responseBody, new TypeReference<ResultWrapper<ScriptEngineInfo>>()
      {
      });
      ScriptEngineInfo scriptEngineInfo = wrapper.getData();
      logger.info("【脚本引擎】版本号：{} ,PID={} 运行正常。", scriptEngineInfo.getVersion(), PID);
      daemonService.updateEngineInfo(scriptEngineInfo);
    } catch (Exception ex)
    {
      logger.info("脚本引擎信息获取失败", ex);
      return false;
    }
    return true;
  }

  @Override
  public String getPid()
  {
    String pidFile = daemonProperties.getEngineHome() + "/" + engineProperties.getPidFile();
    try (Scanner sc = new Scanner(new FileReader(pidFile)))
    {
      while (sc.hasNextLine())
      {  //按行读取字符串
        PID = sc.nextLine();
      }
    } catch (FileNotFoundException e)
    {
      logger.error("脚本引擎的PID文件不存在！" + e.getMessage());
    }
    logger.debug("获取脚本引擎的进程号：{}", PID);
    return PID;
  }

  @Override
  public void shutdown()
  {
    TaskKill taskKill = new TaskKill();
    taskKill.force(true);
    String pid = getPid();
    if (pid != null && pid.trim().length() > 0)
    {
      taskKill.pid(pid);
      taskKill.execute();
      logger.debug("关闭脚本引擎，根据进程号杀掉进程：PID={}", pid);
    }
  }

}
