package com.bonait.bnframework.HBL.Communication.Siemens;

import com.bonait.bnframework.HBL.DataUtil.Convert;
import com.bonait.bnframework.HBL.Interface.IRun;
import com.bonait.bnframework.HBL.Logs.MessageLog;
import com.bonait.bnframework.HBL.Result.OperateResult;
import com.bonait.bnframework.HBL.Result.OperateResultT;
import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;

public class CommHelper {

    private static CommHelper mInstance; //实例变量设置私有，防止直接通过类名访问

    private CommHelper() { //默认构造函数私有，防止类外直接new创建对象
    }

    public static synchronized CommHelper get() { //静态同步方法作为唯一的实例对象获取方式
        if (mInstance == null) {
            mInstance = new CommHelper();
        }
        return mInstance;
    }
    private String IPAddress="127.0.0.1";
    public boolean IsConnected(){
        return siemens.IsConnected;
    }
    public IRun ConnectOk;

   public SiemensHelper siemens=new SiemensHelper(EPlcType.S200_SMART, IPAddress);

    public void Connect(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                MessageLog.ShowInfo("开始连接PLC");
                int tempFlag=0;
                while   (!siemens.checkConnected()){
                    try{
                        tempFlag++;
                        siemens=new SiemensHelper(EPlcType.S200_SMART, IPAddress);
                        siemens.connect();
                        siemens.Delay(1000);
                    }catch (Exception e){
                        if(tempFlag==1)MessageLog.ShowInfo("PLC连接失败："+e.getMessage());
                        siemens.Delay(1000);
                    }
                }
                if(ConnectOk!=null)ConnectOk.Run();
                siemens.IsConnected=true;
                MessageLog.ShowInfo("PLC连接成功");
            }
        }).start();
    }



    public void writePLC(String add,Object value){
        if(!IsConnected()) {
            MessageLog.ShowInfo(add+"：写入数据失败，连接已断开");
            return;
        }
        if(value==null) {
            MessageLog.ShowInfo("writePLC：写入值为空");
            return;
        }
        try{
            if(add.toUpperCase().contains("VD")){
                Float tempVD= Float.parseFloat(value.toString());
                siemens.WriteFloat32(add,tempVD);
            }
            else if (add.toUpperCase().contains("VW")){
                Integer tempVW= Integer.parseInt(value.toString());
                siemens.WriteUInt16(add,tempVW);
            }
            else if (add.toUpperCase().contains("V")){
                Boolean tempV= Boolean.parseBoolean(value.toString());
                siemens.WriteBoolean(add,tempV);
            }
        }catch (Exception e){
            MessageLog.ShowInfo("writePLC：写入失败，"+e.getMessage());
        }

    }

    public Object readPLC(String add){
        try{
            if(add.toUpperCase().contains("VD")){
               return siemens.ReadFloat32(add);
            }
            else if (add.toUpperCase().contains("VW")||add.toUpperCase().contains("IW")||add.toUpperCase().contains("QW")){
                return siemens.ReadUInt16(add);
            }
            else if (add.toUpperCase().contains("V")){
                return siemens.ReadBoolean(add);
            }
        }catch (Exception e){
            MessageLog.ShowInfo("readPLC：读取失败，"+e.getMessage());
        }
        return new Object();
    }

    public <T> OperateResultT<T> Read(String add){
        if(!IsConnected()) return OperateResultT.CreateFailedT(add+"：读取数据失败，连接已断开");
        OperateResultT<T> result = new OperateResultT<>();
        String typeName=result.Content.getClass() .getName();
        try{
            if(typeName.contains("Boolean")){
                return Convert.TryToGenericity(siemens.ReadBoolean(add));
            }else if(typeName.contains("Integer")){
                if(add.toUpperCase().contains("VD")){
                    return Convert.TryToGenericity(siemens.ReadInt32(add));
                }
                else if (add.toUpperCase().contains("VW")||add.toUpperCase().contains("IW")||add.toUpperCase().contains("QW")){
                    return Convert.TryToGenericity(siemens.ReadUInt16(add));
                }
            }else if(typeName.contains("Short")){
                return Convert.TryToGenericity(siemens.ReadInt16(add));
            }else if(typeName.contains("Float")){
                return Convert.TryToGenericity(siemens.ReadFloat32(add));
            }else{
                return OperateResultT.CreateFailedT(typeName+" 暂不支持的数据类型");
            }
        }catch (Exception e){
            return OperateResultT.CreateFailedT(e);
        }
        return result;
    }

    public <T> OperateResult Write(String add, T value){
        if(!IsConnected()) return OperateResult.CreateFailed(add+"：读取数据失败，连接已断开");
        if(value ==null) return OperateResult.CreateFailed(add+"：写入值无效");
        String typeName=value.getClass() .getName();
        try{

            if(typeName.contains("Boolean")){
                Convert.<Boolean>TryToGenericity(value).OnSource(s->{ siemens.WriteBoolean(add,s.Content);});
            }else if(typeName.contains("Integer")){
                if(add.toUpperCase().contains("VD")){
                    Convert.<Integer>TryToGenericity(value).OnSource(s->{ siemens.WriteInt32(add,s.Content);});
                }
                else if (add.toUpperCase().contains("VW")){
                    Convert.<Integer>TryToGenericity(value).OnSource(s->{ siemens.WriteUInt16(add,s.Content);});
                }
            }else if(typeName.contains("Short")){
                Convert.<Short>TryToGenericity(value).OnSource(s->{ siemens.WriteInt16(add,s.Content);});
            }else if(typeName.contains("Float")){
                Convert.<Float>TryToGenericity(value).OnSource(s->{ siemens.WriteFloat32(add,s.Content);});
            }else{
                return OperateResult.CreateFailed(typeName+" 暂不支持的数据类型");
            }
            return OperateResult.CreateSuccess();
        }catch (Exception e){
            return OperateResult.CreateFailed(e);
        }
    }

}
