package net.northking.cctp.se.debugger.pool;

import net.northking.cctp.se.debugger.MobileDebugger;
import net.northking.cctp.se.dto.ATUWebSocketReplay;
import net.northking.cctp.se.thread.ExecutorPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.websocket.CloseReason;
import javax.websocket.Session;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.*;

import static javax.websocket.CloseReason.CloseCodes.CANNOT_ACCEPT;

public class WebSocketMobileDebuggerPool implements WebSocketDebuggerPool {
  public static final Logger logger = LoggerFactory.getLogger(WebSocketMobileDebuggerPool.class);

  private static WebSocketMobileDebuggerPool instance = new WebSocketMobileDebuggerPool();

  private WebSocketMobileDebuggerPool() {
  }

  public static WebSocketMobileDebuggerPool getInstance() {
    return instance;
  }

  /**
   * 最大在线客户端数量
   */
  private static final int MAX_ONLINE_CLIENT = 5;

  // 移动自动化线程池
  private ExecutorService executorService = new ThreadPoolExecutor(0, MAX_ONLINE_CLIENT,
          0L, TimeUnit.MILLISECONDS,
          new LinkedBlockingQueue<Runnable>());

  private static Map<String, MobileDebugger> debuggerMap = new ConcurrentHashMap<>();

  @Override
  public void createDebugger(Session session, String deviceToken) {
    //校验移动自动化线程是否开启创建
    if(!ExecutorPool.enableMobile){
      try {
        session.close(new CloseReason(CANNOT_ACCEPT, "移动自动化引擎连接已禁用，拒绝连接"));
      } catch (IOException e) {
        logger.info("拒绝创建调试器。关闭会话失败！", e);
      }
    }
    if (MAX_ONLINE_CLIENT >= debuggerMap.size()) {
      MobileDebugger debugger = new MobileDebugger(deviceToken, session); // 创建线程任务
      executorService.submit(debugger);
      debuggerMap.put(deviceToken, debugger);
    } else {
      // 超过最大连接数
      logger.info("引擎的移动自动化已达到最大连接数");
    }
  }

  @Override
  public void destroyDebugger(String deviceToken) {
    if (debuggerMap.containsKey(deviceToken)) {
      debuggerMap.get(deviceToken).close();
    }
  }

  @Override
  public void replayStart(String deviceToken, ATUWebSocketReplay replayRequest) {
    if (debuggerMap.containsKey(deviceToken)) {
      MobileDebugger debugger = debuggerMap.get(deviceToken);
      if (debugger.isStopped()) {
        debugger.replay(replayRequest);
        Thread debuggerThread = new Thread(debugger);
        debuggerThread.setDaemon(true);
        debuggerThread.start();
      }
    }
  }

  @Override
  public void replayStop(String deviceToken) {
    if (debuggerMap.containsKey(deviceToken)) {
      debuggerMap.get(deviceToken).stop();
    }
  }

  /**
   * 访问线程池
   * @return
   */
  public Map<String, MobileDebugger> getPoolInfo(){
    return debuggerMap;
  }
}
