package org.aohe.control;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.Console;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aohe.core.twain.*;
import org.aohe.exceptions.TwainException;
import org.aohe.result.R;
import org.aohe.scan.Source;
import org.aohe.webcam.WebCamUtils;

import java.io.File;
import java.util.*;

@Slf4j
public class Operational {

    
    private static TwainScanner scanner = null;

    public static String selectOperational(String path) {
        JSONObject json = JSONObject.parse(path);

        //操作符
        String function = json.getString("function");
        String type = json.getString("type");
        if("ping".equals(type)){
            return R.ok().toJsonStr();
        }
        if(function == null){
            return R.fail("操作符为空").toJsonStr();
        }
        //参数符
        JSONObject param = json.getJSONObject("params");

        R r = R.ok();
        try {
            if(function.startsWith("001")){
                r = operationalScan(function, r, param);
            }else if (function.startsWith("002")){
                r = operationalCamera(function, r, param);
            }

        } catch (TwainException e) {
            log.error("获取驱动列表失败");
            log.error(e.getMessage());
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            log.error("选择驱动失败");
            log.error(e.getMessage());
            throw new RuntimeException(e);
        }

        return r.toJsonStr();
    }

    private static R operationalCamera(String function, R r, JSONObject param){
        if("002001".equals(function)){
            r = R.ok(WebCamUtils.getWebcams());
        }else if ("002002".equals(function)){
            //设置webcam
            WebCamUtils.setWebcam(param.getString("name"));
            r = R.ok(WebCamUtils.getViewSizes());
        }else if("002003".equals(function)){
            //获取摄像头分辨率
            r = R.ok(WebCamUtils.getViewSizes());
        }else if ("002004".equals(function)){
            //获取摄像头图片
            r = R.ok(Base64.encode(WebCamUtils.getImageInputStream()));
        }else if("002005".equals(function)){
            //打开摄像头传输流
            WebCamUtils.openWebcamTransfer();
        }else if ("002006".equals(function)){
            //设置分辨率
            WebCamUtils.setViewSizes(param.getInteger("width"), param.getInteger("height"));
            r = R.ok();
        }else if("002007".equals(function)){
            //打开摄像头传输流
            WebCamUtils.closeWebcamTransfer();
        }

        return r;
    }

    private static R operationalScan(String function, R r, JSONObject param) throws TwainException, InterruptedException {
        if("001001".equals(function)){
            //获取扫描仪列表
            r = getDevices();
        } else if ("001002".equals(function)) {
            //选择扫描仪
            r = setScanner(param.getString("scannerId"));
        }else if ("001003".equals(function)){
            //获取扫描仪操作符列表
            r = getDeviceOperations();
        }else if ("001004".equals(function)){
            //r = setDeviceOperations();
        }else if ("001007".equals(function)){
            r = setDeviceOperations(param);
        }else if ("001008".equals(function)){
            r = startScan(param.getString("scannerId"));
        }else if ("001012".equals(function)){
            closeTwSource();
        }else if ("001013".equals(function)){
            closeTwSource();
        }else if ("001015".equals(function)){
            r = startScan(param.getString("scannerId"),true);
        }else if ("001016".equals(function)){
            r = startScan(param.getString("scannerId"),true);
        }
        return r;
    }

    /**
     * 001001
     * 获取连接到当前终端的所有扫描仪并返回设备的SN号
     *
     * @return R<list>
     */
    public static R getDevices () throws TwainException {
        return R.ok(TwainSource.getProductNamesToList());
    }

    /**
     * 001002
     * 选中某一获取到的扫描仪
     * @return R<boolean> -> success
     */
    public static R setScanner(String name) throws TwainException, InterruptedException {
        if(name == null || name.isEmpty()){
            return R.fail("扫描仪名字为空");
        }
        TwainScanner.getScanner().select(name);
        Twain.getSourceManager().selectSource(name);

        return R.ok();
    }

    /**
     * 001003
     * 获取当前选中扫描仪可配置的项
     * @return
     */
    public static R getDeviceOperations() throws TwainException {

        try{
            TwainSource twainSource = openTwSource();
            TwainCapability[] capabilities = twainSource.getCapabilities();


            Map<String, List<String>> map = new HashMap<>();
            for (TwainCapability cap : capabilities){
                List<String> list = new ArrayList<>();

                String key  = Twain.getMapCapCodeToName().get(cap.cap);
                String formatKey = String.format("0x%04x", cap.cap);

                list.add(key);
                list.add(formatKey);

                map.put(key,list);
            }
            return  R.ok(map);
        }finally {
            closeTwSource();
        }





    }

    /**
     * 001004
     * 设置或修改当前选中扫描仪某一配置项的能力值
     * DPI --> double
     * 色彩模式 color 0,1,2 -> 黑白，灰度，彩色
     * 进纸模式 paper true,false -> 自动，手动
     * @param map 参数和值
     * @return R
     */
    public static R setDeviceOperations(JSONObject map){
        try {
            TwainSource twainSource = Twain.getSourceManager().getSource();
            // 先约定为三种参数 DPI,色彩模式,进纸模式
            if(map.get("dpi") !=null){
                twainSource.setResolution(map.getDouble("dpi"));
            }
            if(map.get("color") !=null){
                twainSource.setCapability(Twain.ICAP_PIXELTYPE, map.getInteger("color"));
            }
            if(map.get("paper") !=null){
                twainSource.setCapability(Twain.CAP_FEEDERENABLED, map.getBooleanValue("paper"));
            }
        } catch (TwainException e) {
            throw new RuntimeException(e);
        }
        return R.ok();
    }

    /**
     * 001008
     * 当前扫描仪启动扫描
     * @param name 扫描仪名称
     * @return R
     * @throws TwainException default error
     */
    public static R startScan(String name) throws TwainException {
        return startScan(name, false);
    }

    /**
     * 001008
     * 当前扫描仪启动扫描
     * @param name 扫描仪名称
     * @param systemUI 是否使用打印机自带UI
     * @return R
     * @throws TwainException default error
     */
    public static R startScan(String name, boolean systemUI ) throws TwainException {
        Source source = new Source();
        source.setName(name);
        source.setSystemUI(systemUI);
        List<File> fileList = source.scan();
        List<String> base64Files = new ArrayList<>();
        for (File file : fileList){
            base64Files.add(Base64.encode(file));
        }
        return R.ok(base64Files);
    }

    /**
     * 打开接口
     * @return twSource
     * @throws TwainException 默认错误
     */
    public static TwainSource openTwSource() throws TwainException {
        TwainSource twainSource = Twain.getSourceManager().getSource();

        if(twainSource.getState() != 4){
            //打开接口
            Twain.getSourceManager().openSource();
        }
        return twainSource;
    }

    /**
     * 关闭接口
     * @throws TwainException 默认错误
     */
    public static void closeTwSource() throws TwainException {
        TwainSource twainSource = Twain.getSourceManager().getSource();
        twainSource.close();
    }

    public void getSetting(Integer i) throws TwainException {

        try{
            TwainSource twainSource = openTwSource();
            TwainCapability tc = twainSource.getCapability(i);
            Console.log(tc.getItems());
        } catch (TwainException e) {
            throw new RuntimeException(e);
        } finally {
            closeTwSource();
        }
    }
}
