#include "CocoLoader.h"
#include "zlib.h"

using namespace std;
using namespace rapidjson;

namespace cocostudio{
    

char	cTypeName[] = {'N','F','T','O','A','S','V'};
const	char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" };
const   char* kObjKeyName[] = { "__type" , "classname" };
char	g_Buff[2048];

char*	stExpCocoAttribDesc::GetName(CocoLoader* pCoco)
{
    return ( pCoco->GetMemoryAddr_String() + m_szName );
}

char*	stExpCocoObjectDesc::GetName(CocoLoader* pCoco)
{
    return ( pCoco->GetMemoryAddr_String() + m_szName );
}

int	stExpCocoObjectDesc::GetAttribNum()
{
    return m_cAttribNum;
}

stExpCocoAttribDesc* stExpCocoObjectDesc::GetAttribDescArray(CocoLoader* pCoco)
{
    return (stExpCocoAttribDesc*)( pCoco->GetMemoryAddr_AttribDesc() + m_pAttribDescArray );
}
    
Type stExpCocoNode::GetType(CocoLoader*	pCoco)
{
    
    Type	tType = kObjectType;
    if(m_ObjIndex >= 0)
    {
        stExpCocoObjectDesc*	tpCocoObjectDesc = pCoco->GetCocoObjectDescArray() ;
        if( m_AttribIndex >= 0 )
        {
            stExpCocoAttribDesc* tpAttribDescArray = (stExpCocoAttribDesc*) tpCocoObjectDesc[m_ObjIndex].GetAttribDescArray(pCoco);
            tType = Type(tpAttribDescArray[m_AttribIndex].m_cTypeName - 'N' + kNullType);
            
            if(kFalseType == tType || kTrueType == tType)
            {
                char* szValue = (char*)GetValue(pCoco);
                if(szValue[0] == '0')
                {
                    return kFalseType;
                }
                else
                {
                    return kTrueType;
                }
            }
            
        }
        else
        {
            tType = kObjectType;
        }
    }
    else
    {
        if(m_AttribIndex >= 0)
        {
            tType   = (Type)m_ChildNum;
            
            if(kFalseType == tType || kTrueType == tType)
            {
                char* szValue = (char*)GetValue(pCoco);
                if(szValue[0] == '0')
                {
                    return kFalseType;
                }
                else
                {
                    return kTrueType;
                }
            }
        }
        else
        {
            tType = kArrayType;
        }
    }
    return tType;
}

char*	stExpCocoNode::GetName(CocoLoader*		pCoco)
{
    char*   szName  = nullptr ;
    if(m_ObjIndex >= 0)
    {
        stExpCocoObjectDesc*	tpCocoObjectDesc = pCoco->GetCocoObjectDescArray();
        if( m_AttribIndex >= 0 )
        {
            stExpCocoAttribDesc* tpAttribDescArray = (stExpCocoAttribDesc*) tpCocoObjectDesc[m_ObjIndex].GetAttribDescArray(pCoco);
            szName = tpAttribDescArray[m_AttribIndex].GetName(pCoco);
        }
        else
        {
            char* szValue = GetValue(pCoco);
            if(szValue[0])
            {
                szName = GetValue(pCoco);
            }
            else
            {
                szName = tpCocoObjectDesc[m_ObjIndex].GetName(pCoco);
            }
        }
    }
    else
    {
        if(m_AttribIndex >= 0)
        {
            char*   pStringAddr = (char*)pCoco->GetCocoObjectDescArray() + pCoco->GetFileHeader()->m_lStringMemAddr ;
            szName  = m_ChildArray + pStringAddr;	
        }
        else
        {
            szName = (char*)GetValue(pCoco);
        }
    }
    return szName ;
    
}

char* stExpCocoNode::GetValue(CocoLoader* pCoco)
{
	char* szValue = ( pCoco->GetMemoryAddr_String() + m_szValue );
	if( 0==strcmp(szValue,"null") && GetType(pCoco) == kStringType ) 
	{
		strcpy(szValue,"");
	}
	return szValue;
}


int	stExpCocoNode::GetChildNum()
{
    return m_ChildNum;
}

stExpCocoNode*	stExpCocoNode::GetChildArray(CocoLoader* pCoco)
{
    return (stExpCocoNode*)( pCoco->GetMemoryAddr_CocoNode() + m_ChildArray );
}

CocoLoader::CocoLoader()
{
    m_pRootNode = nullptr;
    m_pObjectDescArray = nullptr;
    m_pMemoryBuff = nullptr;
}

CocoLoader::~CocoLoader()
{
    if(m_pMemoryBuff)
    {
        delete[] m_pMemoryBuff;
        m_pMemoryBuff = nullptr;
    }
    
}

bool	CocoLoader::ReadCocoBinBuff(char* pBinBuff)
{
    if(m_pMemoryBuff)return true;
	char*	pTempBuff = pBinBuff;
    
	m_pFileHeader = (stCocoFileHeader*)pTempBuff;
	pTempBuff += sizeof(stCocoFileHeader);
	char*   pStartAddr = m_pMemoryBuff = pTempBuff;
    
	char*	pDestBuff = new char[m_pFileHeader->m_nDataSize];
	if (m_pFileHeader->m_nCompressSize > 0)
	{
		uLongf		dwSrcSize  = m_pFileHeader->m_nCompressSize;
		uLongf		dwDestSize  = m_pFileHeader->m_nDataSize;
		uncompress((Bytef*)pDestBuff,&dwDestSize,(Bytef*)m_pMemoryBuff,dwSrcSize);
	}
	else
	{
		memcpy(pDestBuff, m_pMemoryBuff, m_pFileHeader->m_nDataSize);
	}
	pStartAddr = m_pMemoryBuff = pDestBuff;
    
	m_pObjectDescArray = (stExpCocoObjectDesc*)pStartAddr;
    
	char*	pCocoMemAddr = pStartAddr + m_pFileHeader->m_CocoNodeMemAddr;
    
	m_pRootNode = (stExpCocoNode*)pCocoMemAddr;
    
	return true;
}

char*	CocoLoader::GetMemoryAddr_AttribDesc()
{
    return m_pMemoryBuff + m_pFileHeader->m_lAttribMemAddr ;
}

char*	CocoLoader::GetMemoryAddr_CocoNode()
{
    return m_pMemoryBuff + m_pFileHeader->m_CocoNodeMemAddr;
}

char*	CocoLoader::GetMemoryAddr_String()
{
    return m_pMemoryBuff + m_pFileHeader->m_lStringMemAddr ;
    
}
}