package kr.co.icontrols.ilp300_700.call;

import android.content.Context;
import android.util.Log;

import java.util.Timer;
import java.util.TimerTask;

import kr.co.icontrols.ilp300_700.MainActivity;
import kr.co.icontrols.ilp300_700.MainActivity.HANDLERMSG;
import kr.co.icontrols.ilp300_700.global.Configure.ConfigValue;
import kr.co.icontrols.ilp300_700.global.Declare;
import kr.co.icontrols.ilp300_700.global.Declare.DeviceString;
import kr.co.icontrols.ilp300_700.global.Global;
import kr.co.icontrols.ilp300_700.global.ID;

public class CallManager {

    String TAG = "CallManager";

    public boolean bTalkTestModeEnable = false;
    public Timer CallTimer = null;

    boolean bLOG = true;   // true, false
    boolean bLOG_DEBUG = false;   // true, false
    boolean bLOG_INFO = true;   // true, false

    Context mContext;

    private int nCallTimeCntDN = -99;

    private void LOG(String log) {
        if (bLOG) Log.v(TAG, log);
    }

    private void LOG_DEBUG(String log) {
        if (bLOG_DEBUG) Log.d(TAG, log);
    }

    private void LOG_INFO(String log) {
        if (bLOG_INFO) Log.i(TAG, log);
    }

    public void setCallManagerContext(Context context) {
        mContext = context;
    }

    public String makeSIPID(CALLTYPE eCallType, String strDong, String strHo) {
        try {
            LOG_INFO("[makeSIPID] eCallType : " + eCallType + ", strDong : " + strDong + ", strHo : " + strHo);
            String SIPID = "12345678_Resi_0101_0101_01";
            String strDeviceCnt = "01";
            String strType = DeviceString.strType_Resi;

            if (eCallType == CALLTYPE.RESIDENCE) strType = DeviceString.strType_Resi;
            else if (eCallType == CALLTYPE.LOBBY) strType = DeviceString.strType_Lobby;
            else if (eCallType == CALLTYPE.GUARD) strType = DeviceString.strType_Guard;
            else if (eCallType == CALLTYPE.IHUB) strType = DeviceString.strType_Ihub;
            else if (eCallType == CALLTYPE.RENTRESIDENCE) strType = DeviceString.strType_RentResi;

            SIPID = ConfigValue.strSitecode + "_" + strType + "_" + Global.ZeroPadding_Head(4, strDong) + "_" + Global.ZeroPadding_Head(4, strHo) + "_" + strDeviceCnt;
            LOG_INFO("[makeSIPID] SIPID : " + SIPID);

            return SIPID;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] makeSIPID(CALLTYPE eCallType, String strDong, String strHo)");
            e.printStackTrace();
            return "ERROR";
        }
    }

    public String makeSIPID(String strIPAddress) {
        try {
            LOG_INFO("[makeSIPID] strIPAddress : " + strIPAddress);
            String SIPID = "12345678_Resi_0101_0101_01";
            String dong = "101";
            String ho = "101";
            String strType = DeviceString.strType_Resi;
            String strDeviceCnt = "01";

            String[] IP_Parse = strIPAddress.split("\\.");

//            Log.d(TAG, "[makeSIPID] IP_Parse.length = " + IP_Parse.length);
//            for (int i = 0; i < IP_Parse.length; i++)
//            {
//                Log.d(TAG, "IP_Parse[" + i + "] : " + IP_Parse[i]);
//            }

            dong = Integer.toString((((Integer.parseInt(ConfigValue.strDevice_Dong) / 100) * 100) + Integer.parseInt(IP_Parse[1])));

            if (IP_Parse[2].equals("128")) {
                // 경비실폰
                strType = DeviceString.strType_Guard;
                ho = IP_Parse[3];
            } else if (IP_Parse[2].equals("0")) {
                // 로비폰
                strType = DeviceString.strType_Lobby;
                ho = IP_Parse[3];
            } else if (IP_Parse[2].equals("201")) {
                // 아이허브
                strType = DeviceString.strType_Ihub;
                ho = IP_Parse[3];
            } else {
                strType = Declare.DeviceString.strType_Resi;
                ho = IP_Parse[2] + Global.ZeroPadding_Head(2, IP_Parse[3]);
            }

//            Log.d(TAG, "[makeSIPID] dong = " + dong + ", ho = " + ho);

            SIPID = ConfigValue.strSitecode + "_" + strType + "_" + Global.ZeroPadding_Head(4, dong) + "_" + Global.ZeroPadding_Head(4, ho) + "_" + strDeviceCnt;

            LOG_INFO("[makeSIPID] SIPID : " + SIPID);

            return SIPID;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] MakeSIPID(...) : " + e);
            e.printStackTrace();
            return "ERROR";
        }
    }

    public CALLTYPE getCallType_IP(String strIPAddress) {
        try {
            LOG("[getCallType] strIPAddress = " + strIPAddress);

            String[] IP_Parse = strIPAddress.split("\\.");

            if (IP_Parse[2].equals("128")) return CALLTYPE.GUARD;
            else if (IP_Parse[2].equals("0")) return CALLTYPE.LOBBY;
            else if (IP_Parse[2].equals("201")) return CALLTYPE.IHUB;
            else return CALLTYPE.RESIDENCE;
        } catch (Exception e) {
            Log.e(TAG, "[getCallType] getCallType_IP(strIPAddress) + e");
            e.printStackTrace();
            return CALLTYPE.NONE;
        }
    }

    public CALLTYPE getCallType_SIPID(String strSIPID) {
        try {
            if (strSIPID.contains("_Resi_")) return CALLTYPE.RESIDENCE;
            else if (strSIPID.contains("_Guard_")) return CALLTYPE.GUARD;
            else if (strSIPID.contains("_Lobby_")) return CALLTYPE.LOBBY;
            else return CALLTYPE.NONE;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getCallType_SIPID(String strSIPID)");
            e.printStackTrace();
            return CALLTYPE.ERROR;
        }
    }

    public void setCallTimer(int nTimeout) {
        try {
            LOG_INFO("[setFireAlarmProcess] nTimeout = " + nTimeout);
            LOG_INFO("[setFireAlarmProcess] nCallTimeCntDN = " + nCallTimeCntDN);
            if (CallTimer == null) LOG_INFO("[setFireAlarmProcess] FireAlarmTimer is null");
            else LOG_INFO("[setFireAlarmProcess] nCallTimeCntDN is not null");

            if (nTimeout > 0) {
                // 타이머를 생성하거나, 시간을 연장한다.
                if (CallTimer == null && nCallTimeCntDN < 0) {
                    LOG_INFO("[setFireAlarmProcess] ===== 1 =====");
                    // 타이머를 생성한다.
                    nCallTimeCntDN = nTimeout;
                    CallTimer = new Timer();
                    CallTimer.schedule(new CallTimeCntDown(), 1000, 1000);
                } else {
                    LOG_INFO("[setFireAlarmProcess] ===== 2 =====");
                    nCallTimeCntDN = nTimeout;
                }
            } else {
                // 타이머를 종료한다.
                LOG_INFO("[setFireAlarmProcess] ===== 3 =====");
                if (CallTimer != null) CallTimer.cancel();
                CallTimer = null;
                nCallTimeCntDN = -99;
            }
            LOG_INFO("[setFireAlarmProcess] ===== 4 =====");
        } catch (Exception e) {
            Log.e(TAG, "[Exception] setFireAlarmProcess()");
            e.printStackTrace();
        }
    }

    // 통화패스를 다루는 enum
    public enum CALLPATH {
        NORMAL,
        MOIP,
        MOIP_GUARD,
        MOIP_RESIDENCE,
        PSTN,
        NONE,
        ERROR,
    }

    public enum REMOTECALLOWNER {
        RESIDENCE,
        GUARD,
        NONE,
        ERROR,
    }

    // 통화상태정보를 다루는 enum
    public enum CALLTYPE {
        NONE,
        FRONT,
        RESIDENCE,
        RENTRESIDENCE,
        LOBBY,
        GUARD,
        PSTN,
        IHUB,
        ERROR,
    }

    public enum CALLSTATUS {
        IDLE,   // 대기중
        TRYING_CALL,   // 통화가능여부 확인중
        WAITNG_INVITE_ACK,   // 호출에 대한 응답 대기중
        CALLING,   // 호출중
        CALLED,   // 호출수신중
        TALKING,   // 통화중
        REJECT,   // 거절
        BUSY,   // 통화중 거절
        FORWARD,   // 착신전환
        CANCEL,   // 호출 취소
        END,   // 종료
        PSTN_CID,   // PSTN CID
    }

    // 문자통화모드 메지시 종류
    public enum CHATEVENT {
        TRY,   // 채팅요청
        START,   // 채팅시작
        QUIT,   // 채팅종료
        CANCEL,   // 취소
        OK,   // 요청확인
        BUSY,   // 통화중
        BUSY_SIP,   // SIP 통화중
        REJECT,   // 거절
        NONE,
        ERROR,
    }

    public enum CHATSTATUS {
        IDLE,   // 대기
        RINGING,   // 연결중
        TALKING,   // 통화중
        NONE,
        ERROR,
    }
    public enum PSTNEVENTTYPE {
        RINGING,
        RINGING_END,
        CID
    }
    public enum CALLEVENTTYPE {
        SIP_RECEIVE_CALL,   // MoIP 호출 수신
        SIP_RECEIVE_CALL_ACK,   // MoIP 호출응답 수신
        SIP_CONNECT_CALL,   // MoIP 통화 시작
        SIP_TERMINATE_CALL,   // MoIP 통화 종료
        SIP_CANCEL_CALL,   // MoIP 호출 취소
        SIP_REJECT_CALL,   // MoIP 호출수신 거절
        SIP_REJECT_BUSY_CALL,   // MoIP 통화중 호출수신 거절
        SIP_REJECT_BUSY_CHAT_CALL,   // CHAT 통화중 호출수신 거절
        SIP_FORWARD_CALL,   // MoIP 착신전환 설정
        SIP_VIDEO_SET,   // MoIP 영상통화 설정
        PSTN_RINGING,   // PSTN Ring 수신
        PSTN_RINGING_END,   // PSTN Ring 종료
        PSTN_TALKING,   // PSTN 통화
        PSTN_CID,   // PSTN CID
        CHAT_RECEIVE_CALL,   // 문자통화 호출 수신
        CHAT_RECEIVE_CALL_ACK,   // 문자통화 호출응답 수신
        CHAT_CONNECT_CALL,   // 문자통화 시작
        CHAT_TERMINATE_CALL,   // 문자통화 종료
        CHAT_CANCEL_CALL,   // 문자통화 호출 취소
        CHAT_REJECT_CALL,   // 문자통화 호출수신 거절
        CHAT_REJECT_BUSY_CALL,   // 문자통화중 호출수신 거절
        CHAT_REJECT_BUSY_SIP_CALL,   // SIP통화중 호출수신 거절
        CHAT_FORWARD_CALL,   // 문자통화 착신전환 설정
        CHAT_ERROR,   // 문자통화 에러
        CHAT_NONE,   // 문자통화 미설정
    }

    public class CallInfo {
        public int IDLECNT_MAX = 6;
        protected Status mStatus = new Status();

        private REMOTECALLOWNER eRemoteCallOwner = REMOTECALLOWNER.NONE;

        public void setCallStatus(CALLTYPE eType, CALLSTATUS eStatus) {
            LOG_INFO("[setCallStatus] eType = " + eType + ", eStatus = " + eStatus);
            if (eType == CALLTYPE.RESIDENCE) mStatus.RESI = eStatus;
            else if (eType == CALLTYPE.LOBBY) mStatus.LOBBY = eStatus;
            else if (eType == CALLTYPE.GUARD) mStatus.GUARD = eStatus;
            else if (eType == CALLTYPE.FRONT) mStatus.FRONT = eStatus;
            else if (eType == CALLTYPE.PSTN) mStatus.PSTN = eStatus;
            else if (eType == CALLTYPE.IHUB) mStatus.IHUB = eStatus;
        }

        public void setRemoteCallOwner(REMOTECALLOWNER eRemoteCallowner) {
            LOG_INFO("[setRemoteCallOwner] eRemoteCallowner [" + eRemoteCallowner + "]");
            eRemoteCallOwner = eRemoteCallowner;
        }

        public REMOTECALLOWNER geteRemoteCallOwner() {
            return eRemoteCallOwner;
        }

        public CALLSTATUS getRESI() {
            return mStatus.RESI;
        }

        public CALLSTATUS getLOBBY() {
            return mStatus.LOBBY;
        }

        public CALLSTATUS getGUARD() {
            return mStatus.GUARD;
        }

        public CALLSTATUS getFRONT() {
            return mStatus.FRONT;
        }

        public CALLSTATUS getPSTN() {
            return mStatus.PSTN;
        }

        public CALLSTATUS getIHUB() {
            return mStatus.IHUB;
        }

        public int getIDLECnt() {
            int nIdleCnt = 0;
            if (mStatus.RESI == CALLSTATUS.IDLE) nIdleCnt++;
            if (mStatus.LOBBY == CALLSTATUS.IDLE) nIdleCnt++;
            if (mStatus.GUARD == CALLSTATUS.IDLE) nIdleCnt++;
            if (mStatus.FRONT == CALLSTATUS.IDLE) nIdleCnt++;
            if (mStatus.PSTN == CALLSTATUS.IDLE) nIdleCnt++;
            if (mStatus.IHUB == CALLSTATUS.IDLE) nIdleCnt++;
            LOG_INFO("[getIDLECnt] nIdleCnt = " + nIdleCnt);
            return nIdleCnt;
        }

        public int getCallingCnt() {
            int nCallingCnt = 0;
            if (mStatus.FRONT == CALLSTATUS.CALLING) nCallingCnt++;
            if (mStatus.LOBBY == CALLSTATUS.CALLING) nCallingCnt++;
            if (mStatus.GUARD == CALLSTATUS.CALLING) nCallingCnt++;
            if (mStatus.RESI == CALLSTATUS.CALLING) nCallingCnt++;
            if (mStatus.IHUB == CALLSTATUS.CALLING) nCallingCnt++;
            if (mStatus.PSTN == CALLSTATUS.CALLING) nCallingCnt++;
            LOG_INFO("[getCallingCnt] nCallingCnt = " + nCallingCnt);
            return nCallingCnt;
        }

        public int getCalledCnt() {
            int nCalledCnt = 0;
            if (mStatus.FRONT == CALLSTATUS.CALLED) nCalledCnt++;
            if (mStatus.LOBBY == CALLSTATUS.CALLED) nCalledCnt++;
            if (mStatus.GUARD == CALLSTATUS.CALLED) nCalledCnt++;
            if (mStatus.RESI == CALLSTATUS.CALLED) nCalledCnt++;
            if (mStatus.IHUB == CALLSTATUS.CALLED) nCalledCnt++;
            if (mStatus.PSTN == CALLSTATUS.CALLED) nCalledCnt++;
            LOG_INFO("[getCalledCnt] nCalledCnt = " + nCalledCnt);
            return nCalledCnt;
        }

        public int getTalkingCnt() {
            int nTalkingCnt = 0;
            if (mStatus.RESI == CALLSTATUS.TALKING) nTalkingCnt++;
            if (mStatus.LOBBY == CALLSTATUS.TALKING) nTalkingCnt++;
            if (mStatus.GUARD == CALLSTATUS.TALKING) nTalkingCnt++;
            if (mStatus.FRONT == CALLSTATUS.TALKING) nTalkingCnt++;
            if (mStatus.PSTN == CALLSTATUS.TALKING) nTalkingCnt++;
            if (mStatus.IHUB == CALLSTATUS.TALKING) nTalkingCnt++;
            LOG_INFO("[getTalkingCnt] nTalkingCnt = " + nTalkingCnt);
            return nTalkingCnt;
        }

        public CALLTYPE getCallingType() {
            CALLTYPE eRemoteType = CALLTYPE.NONE;
            if (getCallingCnt() > 1) {
                eRemoteType = CALLTYPE.ERROR;
            } else {
                if (mStatus.FRONT == CALLSTATUS.CALLING) eRemoteType = CALLTYPE.FRONT;
                else if (mStatus.LOBBY == CALLSTATUS.CALLING) eRemoteType = CALLTYPE.LOBBY;
                else if (mStatus.GUARD == CALLSTATUS.CALLING) eRemoteType = CALLTYPE.GUARD;
                else if (mStatus.RESI == CALLSTATUS.CALLING) eRemoteType = CALLTYPE.RESIDENCE;
                else if (mStatus.IHUB == CALLSTATUS.CALLING) eRemoteType = CALLTYPE.IHUB;
                else if (mStatus.PSTN == CALLSTATUS.CALLING) eRemoteType = CALLTYPE.PSTN;
                else eRemoteType = CALLTYPE.NONE;
            }
            LOG_INFO("[getCallingType] eRemoteType = " + eRemoteType);
            return eRemoteType;
        }

        public CALLTYPE getCalledType() {
            CALLTYPE eRemoteType = CALLTYPE.NONE;
            if (getCalledCnt() > 1) {
                eRemoteType = CALLTYPE.ERROR;
            } else {
                if (mStatus.FRONT == CALLSTATUS.CALLED) eRemoteType = CALLTYPE.FRONT;
                else if (mStatus.LOBBY == CALLSTATUS.CALLED) eRemoteType = CALLTYPE.LOBBY;
                else if (mStatus.GUARD == CALLSTATUS.CALLED) eRemoteType = CALLTYPE.GUARD;
                else if (mStatus.RESI == CALLSTATUS.CALLED) eRemoteType = CALLTYPE.RESIDENCE;
                else if (mStatus.IHUB == CALLSTATUS.CALLED) eRemoteType = CALLTYPE.IHUB;
                else if (mStatus.PSTN == CALLSTATUS.CALLED) eRemoteType = CALLTYPE.PSTN;
                else eRemoteType = CALLTYPE.NONE;
            }
            LOG_INFO("[getCalledType] eRemoteType = " + eRemoteType);
            return eRemoteType;
        }

        public CALLTYPE getTalkingType() {
            CALLTYPE eRemoteType = CALLTYPE.NONE;
            if (getTalkingCnt() > 1) {
                eRemoteType = CALLTYPE.ERROR;
            } else {
                if (mStatus.FRONT == CALLSTATUS.TALKING) eRemoteType = CALLTYPE.FRONT;
                else if (mStatus.LOBBY == CALLSTATUS.TALKING) eRemoteType = CALLTYPE.LOBBY;
                else if (mStatus.GUARD == CALLSTATUS.TALKING) eRemoteType = CALLTYPE.GUARD;
                else if (mStatus.RESI == CALLSTATUS.TALKING) eRemoteType = CALLTYPE.RESIDENCE;
                else if (mStatus.IHUB == CALLSTATUS.TALKING) eRemoteType = CALLTYPE.IHUB;
                else if (mStatus.PSTN == CALLSTATUS.TALKING) eRemoteType = CALLTYPE.PSTN;
                else eRemoteType = CALLTYPE.NONE;
            }
            LOG_INFO("[getTalkingType] eRemoteType = " + eRemoteType);
            return eRemoteType;
        }

        public void printCallStatus() {
            try {
                LOG_INFO("[printCallStatus] RESI [" + getRESI() + "]");
                LOG_INFO("[printCallStatus] LOBBY [" + getLOBBY() + "]");
                LOG_INFO("[printCallStatus] GUARD [" + getGUARD() + "]");
                LOG_INFO("[printCallStatus] FRONT [" + getFRONT() + "]");
                LOG_INFO("[printCallStatus] PSTN [" + getPSTN() + "]");
                LOG_INFO("[printCallStatus] IHUB [" + getIHUB() + "]");
            } catch (Exception e) {
                Log.e(TAG, "[Exception] printCallStatus() : " + e);
                e.printStackTrace();
            }
        }

        public void resetCallStatus() {
            LOG_INFO("[resetCallStatus] ========== START ==========");
            mStatus.RESI = CALLSTATUS.IDLE;
            mStatus.LOBBY = CALLSTATUS.IDLE;
            mStatus.GUARD = CALLSTATUS.IDLE;
            mStatus.FRONT = CALLSTATUS.IDLE;
            mStatus.PSTN = CALLSTATUS.IDLE;
            mStatus.IHUB = CALLSTATUS.IDLE;
        }

        protected class Status {
            CALLSTATUS RESI = CALLSTATUS.IDLE;
            CALLSTATUS LOBBY = CALLSTATUS.IDLE;
            CALLSTATUS GUARD = CALLSTATUS.IDLE;
            CALLSTATUS FRONT = CALLSTATUS.IDLE;
            CALLSTATUS PSTN = CALLSTATUS.IDLE;
            CALLSTATUS IHUB = CALLSTATUS.IDLE;
        }

    }

    public class CTT {   // CTT = Call Timeout Table, 단위 Sec
        public int TIMEOUT_SEC_10 = 10;
        public int TIMEOUT_SEC_30 = 30;
        public int TIMEOUT_SEC_60 = 60;
        public int TIMEOUT_SEC_180 = 180;
        public int WAITNG_INVITE_ACK = 10;
        public int CALLING = 30;
        public int CALLED = 35;
        public int RESIDENCEnRESIDENCE = 180;
        public int RESIDENCEnLOBBY = 60;
        public int RESIDENCEnGUARD = 180;
        public int RESIDENCEnFRONT = 60;
        public int LOBBYnGUARD = 60;
        public int GUARDnGUARD = 180;
        public int GUARDnIHUB = 180;
        public int KILLTIMER = -99;

        public void setTalkTestMode() {
            RESIDENCEnRESIDENCE = 9999999;
            RESIDENCEnLOBBY = 999999;
            RESIDENCEnGUARD = 999999;
            RESIDENCEnFRONT = 999999;
            LOBBYnGUARD = 999999;
            GUARDnGUARD = 999999;
            GUARDnIHUB = 999999;
        }

        public void setTalkNormalMode() {
            RESIDENCEnRESIDENCE = 180;
            RESIDENCEnLOBBY = 60;
            RESIDENCEnGUARD = 180;
            RESIDENCEnFRONT = 60;
            LOBBYnGUARD = 60;
            GUARDnGUARD = 180;
            GUARDnIHUB = 180;
        }
    }

    public class CallTimeCntDown extends TimerTask {
        @Override
        public void run() {
//            LOG_DEBUG("[CallTimeCntDown().run()] Start!!");
            try {
                nCallTimeCntDN--;
                LOG_INFO("[CallTimerCntDown] nCallTimeCntDN = " + nCallTimeCntDN);
                if (nCallTimeCntDN <= 0) {
                    // 통화를 종료하고 타이머를 종료한다.
                    if (CallTimer != null) CallTimer.cancel();
                    nCallTimeCntDN = -99;
                    CallTimer = null;
                    Global.stopMelodyRepeat();
                    MainActivity.mCallController.ui_callEnd();
                    if (Global.nCurrentScreenID != ID.SCREENS.Main) {
                        MainActivity.mCallController.mVideoJNI.mV40IFCCD.videoSet(false);
                        ((MainActivity) mContext).sendHandlerMsgDelayed(HANDLERMSG.CLEAR_ALL_CALL, 0, 0, 100);
                    }
                    LOG_INFO("[CallTimerCntDown] Call End!!");
                }
            } catch (Exception e) {
                Log.e(TAG, "[Exception] FireAlarmCntDown().run() : " + e);
                e.printStackTrace();
            }
        }
    }


}