package com.peergine.android.conference;

import com.peergine.plugin.lib.pgLibJNINode;

import static com.peergine.android.conference.OnEventConst.*;
import static com.peergine.android.conference.pgLibConference2._ObjPeerBuild;
import static com.peergine.android.conference.pgLibConference2._ObjPeerParsePeer;
import static com.peergine.android.conference.pgLibConference2._OutString;
import static com.peergine.android.conference.pgLibConference2._ParseInt;
import static com.peergine.android.conference.pgLibConference2._isEmpty;
import static com.peergine.android.conference.pgLibError.PG_ERR_BadParam;
import static com.peergine.android.conference.pgLibError.PG_ERR_BadPass;
import static com.peergine.android.conference.pgLibError.PG_ERR_BadStatus;
import static com.peergine.android.conference.pgLibError.PG_ERR_Normal;
import static com.peergine.android.conference.pgLibError.PG_ERR_Opened;
import static com.peergine.android.conference.pgLibNode.PG_METH_COMMON_SetOption;
import static com.peergine.android.conference.pgLibNode.PG_METH_FILE_Cancel;
import static com.peergine.android.conference.pgLibNode.PG_METH_FILE_Get;
import static com.peergine.android.conference.pgLibNode.PG_METH_FILE_Put;
import static com.peergine.android.conference.pgLibNode.PG_METH_FILE_Status;
import static com.peergine.android.conference.pgLibNode.PG_METH_PEER_Message;

public class FileTransfer {
    private static final String PARAM_FILE_GET_REQUEST = "FileGetRequest";
    private static final String PARAM_FILE_PUT_REQUEST = "FilePutRequest";

    //------------------------------------------------------
    // File handles.

    private pgLibJNINode m_Node = null;
    private String m_sUser = "";

    private String m_sListFile = "";

    private OnEventListener m_OnEventListener = null;
    private void _OnEvent(String sAct,String sData, String sPeer,String sConfName,String sEventParam){
        if(m_OnEventListener !=null){
            m_OnEventListener.event(sAct,sData,sPeer,sConfName,sEventParam);
        }
    }
    public int Initialize(pgLibJNINode Node ,String sUser ,OnEventListener onEventListener){
        m_Node = Node;
        m_sUser = sUser;
        m_OnEventListener = onEventListener;
        return 0;
    }

    public int FileSessionRequest(String sObjPeer,String sParam){
        if(_isEmpty(sObjPeer)){
            return PG_ERR_BadParam;
        }
        String sFileSession = _FileBuildSession(m_sUser,sObjPeer);
        String sData = "FSessReq?";

        return m_Node.ObjectRequest(sObjPeer, PG_METH_PEER_Message, sData, sParam);
    }

    public void _OnFileSessionRequest(int iHandle, String sObjPeer){
        int iErrCode = PG_ERR_Normal;
        String sPeer = _ObjPeerParsePeer(sObjPeer);


        m_Node.ObjectExtReply(sObjPeer, iErrCode, "", iHandle);
    }
    public int _OnFileSessionResponse(String sObj, int iErr, String sData){


        return 0;
    }

    private String _FileBuildSession(String sUser,String sPeer){
        String sSession =  (sUser + sPeer);
        if (sSession.length() > 120) {
            return sSession.substring(0,120);
        }
        return sSession;
    }

    private String _FileBuildObject(String sSession) {
        String sObjFile = ("File_" + sSession);
        if (sObjFile.length() > 127) {
            return sObjFile.substring(0,126);
        }
        return sObjFile;
    }
    private String _FileObjectParseFileSession(String sObject) {
        String sCapRender = "";
        if (sObject.indexOf("File_") == 0) {
            sCapRender = sObject.substring(5);
        }
        return sCapRender;
    }

    private boolean _FileObjectIs(String sObject) {
        return (sObject.indexOf("File_") == 0);
    }

    private String _FileListSearch(String sFileSession) {
        return m_Node.omlGetEle(m_sListFile, ("\n*" + sFileSession), 1, 0);
    }

    private boolean _FileListAdd(String sFileSession,String sMasterPeer) {
        String sFile = _FileListSearch(sFileSession);
        if ("".equals(sFile)) {
            m_sListFile += "(" + m_Node.omlEncode(sFileSession) + "){(Status){0}(Handle){0}}";
        }

        String sObjFile = _FileBuildObject(sFileSession);

        if (!"PG_CLASS_File".equals(m_Node.ObjectGetClass(sFileSession))) {
            String sObj = _ObjPeerBuild(sMasterPeer);
            if (!m_Node.ObjectAdd(sObjFile, "PG_CLASS_File", sObj, 0x10000)) {
                _OutString("_FileListAdd: Add '" + sObjFile + "' failed!");
                return false;
            }
        }

        return true;
    }

    private boolean _FileListDelete(String sFileSession) {
        String sObjFile = _FileBuildObject(sFileSession);

        m_Node.ObjectRequest(sObjFile, 35, "", "");
        m_Node.ObjectDelete(sObjFile);

        String sFile = _FileListSearch(sFileSession);
        if (!"".equals(sFile)) {
            m_sListFile = m_Node.omlDeleteEle(m_sListFile, ("\n*" + sFileSession), 1, 0);
            return true;
        }

        return false;
    }

    private boolean _FileListSet(String sFileSession, String sItem, String sValue) {
        String sFile = _FileListSearch(sFileSession);
        if (!"".equals(sFile)) {
            String sPath = "\n*" +  sFileSession + "*" + sItem;
            m_sListFile = m_Node.omlSetContent(m_sListFile, sPath, sValue);
            return true;
        }
        return false;
    }

    private String _FileListGet(String sFileSession, String sItem) {
        String sPath = "\n*" + sFileSession + "*" + sItem;
        return m_Node.omlGetContent(m_sListFile, sPath);
    }

    private int _FileRequest(String sFileSession, String sPath, String sPeerPath, int iMethod) {
        if ("1".equals(_FileListGet(sFileSession, "Status"))) {
            return PG_ERR_Opened;
        }

        String sData = "(Path){" + m_Node.omlEncode(sPath) + "}(PeerPath){"
                + m_Node.omlEncode(sPeerPath) + "}(TimerVal){1}(Offset){0}(Size){0}";

        String sParam = (iMethod == 32) ? "FilePutRequest" : "FileGetRequest";

        String sObjFile = _FileBuildObject(sFileSession);
        int iErr =  m_Node.ObjectRequest(sObjFile, iMethod, sData, sParam);
        if (iErr > PG_ERR_Normal) {
            _OutString("_FileRequest: iMethod=" + iMethod + ", iErr=" + iErr);
            return iErr;
        }

        _FileListSet(sFileSession, "Status", "1");
        return iErr;
    }

    private int _FileReply(int iErrReply, String sFileSession, String sPath) {

        String sData = "";
        if (iErrReply != PG_ERR_Normal) {
            _FileListSet(sFileSession, "Status", "0");
        }
        else {
            _FileListSet(sFileSession, "Status", "1");
            sData = "(Path){" + m_Node.omlEncode(sPath) + "}(TimerVal){1}";
        }

        _OutString("_FileReply: iErrReply=" + iErrReply + ", sFileSession=" + sFileSession + ", sData=" + sData);

        String sHandle = _FileListGet(sFileSession, "Handle");
        _OutString("_FileReply: sHandle=" + sHandle);

        int iHandle = _ParseInt(sHandle, 0);
        if (iHandle == 0) {
            _FileListSet(sFileSession, "Status", "0");
            return PG_ERR_BadStatus;
        }


        String sObjFile = _FileBuildObject(sFileSession);
        int iErr = m_Node.ObjectExtReply(sObjFile, iErrReply, sData, iHandle);
        if (iErr <= PG_ERR_Normal) {
            _FileListSet(sFileSession, "Handle", "0");
        }

        _OutString("_FileReply: iErr=" + iErr);
        return iErr;
    }

    private int _FileCancel(String sFileSession) {

        String sObjFile = _FileBuildObject(sFileSession);
        int iErr = m_Node.ObjectRequest(sObjFile, 35, "", "FileCancel");
        if (iErr <= PG_ERR_Normal) {
            _FileListSet(sFileSession, "Status", "0");
        }

        return iErr;
    }

    private int _OnFileRequest(String sObj, int iMethod, String sData, int iHandle) {
        String sFileSession = _FileObjectParseFileSession(sObj);

        if ("1".equals(_FileListGet(sFileSession, "Status"))) {
            return PG_ERR_BadStatus;
        }

        _FileListSet(sFileSession,"Handle", (iHandle + ""));
        _FileListSet(sFileSession, "Status", "1");

        _OutString("_OnFileRequest: sData=" + sData);

        String sPeerPath = m_Node.omlGetContent(sData, "PeerPath");
        String sParam = "peerpath=" + sPeerPath;

        if (iMethod == 32) {
            _OnEvent(EVENT_FILE_PUT_REQUEST, sParam, sFileSession,"","");
        }
        else if (iMethod == 33) {
            _OnEvent(EVENT_FILE_GET_REQUEST, sParam, sFileSession,"","");
        }

        return -1; // Async reply
    }


    private int _OnFileStatus(String sObj, String sData,String sObjPeer) {
        String sFileSession = _FileObjectParseFileSession(sObj);
        String sPeer = _ObjPeerParsePeer(sObjPeer);

        String sStatus = m_Node.omlGetContent(sData, "Status");
        int iStatus = _ParseInt(sStatus, -1);
        if (iStatus != 3) {
            String sPath = m_Node.omlGetContent(sData, "Path");
            String sReqSize = m_Node.omlGetContent(sData, "ReqSize");
            String sCurSize = m_Node.omlGetContent(sData, "CurSize");
            String sParam = "path=" + sPath + "&total=" + sReqSize	+ "&position=" + sCurSize;
            _OnEvent(EVENT_FILE_PROGRESS, sParam, sPeer,"",sFileSession);
        }
        else { // Stop
            _FileListSet(sFileSession, "Status", "0");

            String sPath = m_Node.omlGetContent(sData, "Path");
            String sReqSize = m_Node.omlGetContent(sData, "ReqSize");
            String sCurSize = m_Node.omlGetContent(sData, "CurSize");

            String sParam = "path=" + sPath + "&total=" + sReqSize + "&position=" + sCurSize;
            _OnEvent(EVENT_FILE_PROGRESS, sParam, sPeer,"",sFileSession);

            int iCurSize = _ParseInt(sCurSize, 0);
            int iReqSize = _ParseInt(sReqSize, 0);
            if (iCurSize >= iReqSize && iReqSize > 0) {
                _OnEvent(EVENT_FILE_FINISH, sParam, sPeer,"",sFileSession);
            }
            else {
                _OnEvent(EVENT_FILE_ABORT, sParam, sPeer,"",sFileSession);
            }
        }

        return 0;
    }

    private void _OnFileCancel(String sObj,String sObjPeer) {
        String sFileSession = _FileObjectParseFileSession(sObj);
        String sPeer = _ObjPeerParsePeer(sObjPeer);
        if ("".equals(sFileSession)) {
            return;
        }

        _FileListSet(sFileSession, "Status", "0");
        _OnEvent(EVENT_FILE_ABORT , "",sPeer ,"",sFileSession);
    }

    private int _NodeOnExtRequestFile(String sObj, int uMeth, String sData, int iHandle, String sObjPeer) {
        if (_FileObjectIs(sObj)) {
            if (uMeth == PG_METH_FILE_Put) {
                // put file request
                return _OnFileRequest(sObj, uMeth, sData, iHandle);
            }

            if (uMeth == PG_METH_FILE_Get) {
                // get file request
                return _OnFileRequest(sObj, uMeth, sData, iHandle);
            }

            if (uMeth == PG_METH_FILE_Status) {
                // File transfer status report.
                _OnFileStatus(sObj, sData,sObjPeer);
                return 0;
            }

            if (uMeth == PG_METH_FILE_Cancel) {
                // Cancel file request
                _OnFileCancel(sObj,sObjPeer);
                return 0;
            }

            return 0;
        }

        return 0;
    }

    private int _NodeOnReplyFile(String sObj, int iErr, String sData, String sParam) {
        if (_FileObjectIs(sObj)) {
            if (PARAM_FILE_GET_REQUEST.equals(sParam)
                    || PARAM_FILE_PUT_REQUEST.equals(sParam))
            {
                String sFileSessiom = _FileObjectParseFileSession(sObj);
                String sID = "";
                if (iErr != PG_ERR_Normal) {
                    _FileListSet(sFileSessiom, "Status", "0");
                    _OnEvent(EVENT_FILE_REJECT, (iErr + ""), "","",sFileSessiom);
                    return 1;
                }
                else {
                    _FileListSet(sFileSessiom, "Status", "1");
                    _OnEvent(EVENT_FILE_ACCEPT, "0" , "","",sFileSessiom);
                    return 1;
                }
            }

            return 1;
        }
        return 1;
    }
}
