#pragma once
#include "../KbUnArc.h"

extern "C"
{
#include "lzma/c/7z.h"
#include "lzma/c/7zAlloc.h"
#include "lzma/c/7zBuf.h"
#include "lzma/c/7zCrc.h"
#include "lzma/c/7zFile.h"
#include "lzma/c/7zVersion.h"

};
#include "kpi.h"

class KbUn7z : public KbUnArc 
{
protected:
    struct LookInStream : public ILookInStream
    {//7zTypes.h::CLookToRead2 相当
        IKpiFile *pFile;
        size_t pos;
        size_t size;
        Byte buf[(1 << 14)];
        static SRes look(const ILookInStream *p, const void **buf, size_t *size);
        static SRes skip(const ILookInStream *p, size_t offset);
        static SRes read(const ILookInStream *p, void *buf, size_t *size);
        static SRes seek(const ILookInStream *p, Int64 *pos, ESzSeek origin);
        LookInStream(void){
            Look = look;
            Skip = skip;
            Read = read;
            Seek = seek;
            pFile = NULL;
            pos = size = 0;
        }
    };
    LookInStream  m_lookStream;
    CSzArEx       m_szAr;

    static void *un7z_alloc(ISzAllocPtr p, size_t size){return malloc(size);}
    static void  un7z_free(ISzAllocPtr p, void *address){free(address);}
    ISzAlloc     m_allocMain;
    ISzAlloc     m_allocTemp;
    UINT64       m_qwTotalSize;   //全展開後のサイズ
    //UINT64       m_qwLimitSize;   //全展開後のサイズの制限値(超えてたら解凍に失敗させる)
    /*
    if you need cache, use these 3 variables.
    if you use external function, you can make these variable as static.
    */
    IKpiFile   *m_pFile;
    UInt32  m_blockIndex;// = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
    size_t  m_outBufferSize;// = 0;  /* it can have any value before first call (if outBuffer = 0) */
    BYTE  **m_outBuffers;

    BOOL    m_bEnablePPMD;
    BOOL    m_bIsPPMD;
    struct SevenZipInfo
    {
        KPI_FILEINFO fi;
        BOOL         bIsDir;//フォルダのとき TRUE
        int          nState;//0:未処理、1:展開処理済、-1:失敗
        BYTE        *pData;
        UINT64       qwDataSize;
        wchar_t      szFileName[1];
    };
    HANDLE         m_hHeap;
    SevenZipInfo **m_ppSevenZipInfo;

    SevenZipInfo* __fastcall FindSevenZipInfo(const wchar_t *cszFileName);
    virtual ~KbUn7z(void);
public:
    DWORD __fastcall Find(const wchar_t *cszFileName);
    BOOL  __fastcall Open(IKpiFile *pFile, IKpiFolder *pFolder, const wchar_t *cszOutputPath);

    BOOL WINAPI GetArchiveInfo(const KPI_ARCHIVEINFO **ppArchiveInfo);
    BOOL WINAPI EnumFileInfo(DWORD dwIndex, const KPI_FILEINFO **ppFileInfo);
    BOOL WINAPI Extract(DWORD dwIndex, IKpiFile **ppFile, UINT64 qwSize);

    KbUn7z(UnArcConfig *pConfig);
};

 