package jp.agentec.abook.abv.ui.viewer.foxitPdf;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PointF;

import com.foxit.sdk.PDFException;
import com.foxit.sdk.common.Constants;
import com.foxit.sdk.common.Library;
import com.foxit.sdk.common.Progressive;
import com.foxit.sdk.common.Renderer;
import com.foxit.sdk.common.fxcrt.Matrix2D;
import com.foxit.sdk.common.fxcrt.RectF;
import com.foxit.sdk.common.fxcrt.RectFArray;
import com.foxit.sdk.pdf.PDFDoc;
import com.foxit.sdk.pdf.PDFPage;
import com.foxit.sdk.pdf.TextPage;
import com.foxit.sdk.pdf.TextSearch;

import java.util.ArrayList;
import java.util.List;

import jp.agentec.abook.abv.bl.common.log.Logger;

import static com.foxit.sdk.pdf.PDFDoc.e_PwdNoPassword;


/**
 * Created by leej on 2018/06/11.
 */

public class FoxitPdfCore {

    private static final String TAG = "FoxitPdfCore";

    private Context mContext;
    private String mFilePath;
    private boolean mPasswordError = false;
    private PDFDoc mPDFDoc;

    private static int initErrCode = Constants.e_ErrSuccess;

    private static String sn = "sA/GtgkqEVC8DF1pZxMjg1zAsUMXRtOwVneujMETAMrGBtssoE0f+g==";
    private static String key = "ezJvj18mrBp39Nvimat2lTNmf/fiuEWgv0k5shXKx/J5tNV9GKHFhz5etmdDZ7mfCQVQ8l80DVKvRyRE5Hoe5VfkxAC5WmEvuVq/bDkXBZU1gA/8LTillYeNfOOAcVBuPx5y1wexCJ/b4PT6fmaC6/fqFGfK5oXnP4PV+1gFMSZ03oIrGRusD9fqQ5pxQKjwcXabZrAfu7MIzchMKxC79wFUAZWKUb7aXD1h7i59WB0Wo4Imrq21CMlNf7dAfNWf6Xmhfl0ErFxNEiRnD3nJ2zPbAfO8C3mNez7BsqkrCiA0HECx+o01/fXx7sPxrougpKm5muCnCrBI0DYbs9Vw/pL0MvA6/R9YtjuuYdK684F33crOJMRS/jQ1R00oMhzejuuGCEJyySVK0Ouj0mKf52bzglFioe1SGlQWmyVh6jRbopjgHg0Duy8eL2xznqKBSU8vfnPOq0eBl0JixxNR/B8waEMiKQcHZDKgeCk7ylyv6D/HwSUCJZ1rSzSv+40E6EKumdaSY/KIG3dleHrXwzHQckKxyM6/tWd5OvenoTtUvKTBFvv8DrwW1R47Es/uPf67ntFVO8TvhezkYyQrGpCJ0tjzMzHsodPnFPNBoBJiJWGKCmtc2C2m4yU+A3DP14uS+BmpHOAIAP3sdcY5R/cKFoAg7pOtD52ygeOKRSQk/79CZ4WOS01fnoD7h9VTMQCXELzn6lAwDlFS0fFn3F+6/PmLNMJIJB6raTD+eecItoTqN8dts+yhhFtoFa4PeZsR0CI/3E3j5lZeQ9m4501HZBti0Y7YOWyNKTkkhUdTpBmvSRRMTJksmSH9wlKPhzSTAgHSZRawGKjAZHtSh7bWTK9b7fyTTqrzIiei9v0GmiwNtRKKTLiP+YWOHkq85IzT8lJG3HUkdIXLxKwDF6mr25CqcjEfOSSx6XcTfBAoN1dEcQHlAxMusVVW2Q/KvTN74tkH3g5cMIl/SkOh+tUSsaj22//fvxMB1gsmymCgwSobRX8zJ4TgO8J8enD9IjkFfu/zMyGaAN6HgW3GbvJgHNCAj9zHdqpZ173Nj/R/Lc/GBnJVpMWc23Nj9froMAEYs254TzvEQD1FeMnNXRQWL7SPVQ64rqJGeYOFkr8kjQonB5CPtD7DGjVKWLh56LLuuUpetB25jClGNe3RDBPJP20ukB6S/FQIoApihfONIy0bUoNJgWi5Awjlsq4Q3cPEqvlLPrTNYhxY";

    static {
        System.loadLibrary("rdk");
    }

    public FoxitPdfCore(Context context, String filePath) throws PDFException {
        mContext = context;
        mFilePath = filePath;
        mPDFDoc = new PDFDoc(mFilePath);
        //Foxit PDF SDK library init
        initErrCode = Library.initialize(sn, key);
        if (initErrCode != Constants.e_ErrSuccess) {
            if (initErrCode == Constants.e_ErrInvalidLicense) {
                Logger.e(TAG, "The license is invalid!");
            } else {
                Logger.e(TAG, "Failed to initialize the library!");
            }
            throw new PDFException(initErrCode);
        }
    }

    /**
     * PDFDocを読み込む処理
     * パスワードが必要な場合は、trueで返す
     * @param password
     * @return
     * @throws PDFException
     */
    public boolean loadPDFDoc(byte[] password) throws PDFException {
        int passwordType = e_PwdNoPassword;
        try {
            mPDFDoc.load(password);
            passwordType  = mPDFDoc.getPasswordType();
            if(passwordType != e_PwdNoPassword) {
                return true;
            }
        } catch (PDFException e) {
            Logger.e(TAG, "pdfDoc load Failed.", e);
            throw e;
        }
        return false;
    }

    /**
     * PDFページの読み込む処理
     * @param doc
     * @param index
     * @param parseFlag
     * @return
     */
    public PDFPage loadPage(PDFDoc doc, int index, int parseFlag) {
        PDFPage page = null;
        if (doc == null) {
            Logger.e(TAG, "The document is null!");
            return null;
        }

        try {
            page = doc.getPage(index);
            if (page == null) {
                Logger.e(TAG, "Get Page error");
                return null;
            }

            if (!page.isParsed()) {
                Progressive progressive = page.startParse(parseFlag, null, false);

                int state = Progressive.e_ToBeContinued;
                while (state == Progressive.e_ToBeContinued) {
                    state = progressive.resume();
                }

                progressive.delete();
                if (state == Progressive.e_Error) {
                    Logger.e(TAG, "Parse Page error!");
                    return null;
                }
            }

        } catch (PDFException e) {
            Logger.e(TAG, "Load Page error.");
        }
        return page;
    }

    public void releaseDoc() {
        mPDFDoc.delete();
    }

    /**
     * PDFのページ数取得
     * @return
     * @throws PDFException
     */
    public int countPages() throws PDFException {
        return mPDFDoc.getPageCount();
    }

    /**
     * PDFサイズ取得
     * @param pageIndex
     * @return
     * @throws PDFException
     */
    public PointF getPageSize(int pageIndex) throws PDFException {
        Logger.i("getPageSize : " + pageIndex);
        PDFPage pdfPage = mPDFDoc.getPage(pageIndex);
        return new PointF(pdfPage.getWidth(), pdfPage.getHeight());
    }

    /**
     * PDF特定ページのイメージ描画
     * @param bm
     * @param page
     * @param pageW
     * @param pageH
     * @param patchX
     * @param patchY
     * @param patchW
     * @param patchH
     * @return
     */
    public Bitmap drawPage(int page, int pageW, int pageH, int patchX, int patchY, int patchW, int patchH) {
        Logger.i(TAG, "drawPage start.");
        synchronized (mContext) {
            Bitmap bm = Bitmap.createBitmap(patchW, patchH, Bitmap.Config.ARGB_8888);
            PDFPage pdfPage = loadPage(mPDFDoc, page, PDFPage.e_ParsePageNormal);
            Renderer renderer = null;
            Progressive progressive = null;
            try {
                if (pdfPage.hasTransparency()) {
                    bm.eraseColor(Color.TRANSPARENT);
                } else {
                    bm.eraseColor(Color.WHITE);
                }

                Matrix2D matrix = pdfPage.getDisplayMatrix(-(patchX), -(patchY), pageW, pageH, Constants.e_Rotation0);

                renderer = new Renderer(bm, true);

                progressive = renderer.startRender(pdfPage, matrix, null);
                int state = Progressive.e_ToBeContinued;
                while (state == Progressive.e_ToBeContinued) {
                    state = progressive.resume();
                }
                progressive.delete();
                if (state == Progressive.e_Error) {
                    Logger.e(TAG, "Failed to render the page No.%d failed!", page);
                    return null;
                }
                renderer.delete();
                pdfPage.delete();
            } catch (PDFException e) {
               Logger.e(TAG, "Failed to render the page No.%d! %s", page, e.getMessage());
            }

            Logger.i(TAG, "drawPage end.");
            return bm;
        }
    }

    /**
     * ページの文字検索機能
     * @param page
     * @param searchText
     * @return
     */
    public List<RectF> searchPage(int page, String searchText) {
        List<RectF> rectFList = new ArrayList<>();
        TextSearch textSearch = null;
        try {
            textSearch = new TextSearch(mPDFDoc, null, TextPage.e_ParseTextNormal);
            PDFPage pdfPage = mPDFDoc.getPage(page);
            if (!textSearch.setPattern(searchText)) {
                Logger.e(TAG, "set keywords error");
                textSearch.delete();
                return null;
            }
            textSearch.setStartPage(page);
            textSearch.setEndPage(page);
            while(textSearch.findNext()) {
                if(textSearch.getMatchPageIndex() != page) {
                    break;
                }
                RectFArray rectFArray = textSearch.getMatchRects();
                rectFList.add(rectFArray.getAt(0));
            }
        } catch (PDFException e) {
            Logger.e(TAG, "PDF searchText failed.", e);
        } finally {
            if (textSearch != null) {
                textSearch.delete();
            }
            return rectFList.size() > 0 ? rectFList : null;
        }
    }

}
