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

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import jp.agentec.abook.abv.bl.acms.client.json.DownloadedContentInfoJSON;
import jp.agentec.abook.abv.bl.acms.client.json.content.ContentJSON;
import jp.agentec.abook.abv.bl.common.ABVEnvironment;
import jp.agentec.abook.abv.bl.common.exception.ABVRuntimeException;
import jp.agentec.abook.abv.bl.common.log.Logger;
import jp.agentec.abook.abv.bl.common.util.ContentFileUtil;
import jp.agentec.abook.abv.bl.download.ContentFileExtractor;
import jp.agentec.abook.abv.bl.logic.AbstractLogic;
import jp.agentec.abook.abv.bl.logic.ContentLogic;
import jp.agentec.abook.abv.cl.util.BitmapUtil;
import jp.agentec.abook.abv.launcher.android.R;
import jp.agentec.abook.abv.ui.viewer.view.ThumbnailSeekBarLayout;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;

import com.foxit.sdk.PDFException;


public class PdfThumbnailProvider {
	private static final String TAG = "PDFThumbnailProvider";
	
	public int landHeightS = 39;
	public int landWidthS = 52;
	public int portHeightS = 40;
	public int portWidthS = 30;

	public int landHeightM = 51;
	public int landWidthM = 68;
	public int portHeightM = 64;
	public int portWidthM = 48;
	
	public int landHeightL = 135;
	public int landWidthL = 180;
	public int portHeightL = 180;
	public int portWidthL = 135;
	
	private ContentLogic mContentLogic = AbstractLogic.getLogic(ContentLogic.class);
	private FoxitPdfCore mFoxitPdfCore;
	private boolean outputFile = ABVEnvironment.getInstance().isPdfThumbnailOutput;
	private Context mContext;

	private Boolean isLandscape = null;
	private PdfImageProvider pdfImageProvider;
	private long mContentId;
	private Bitmap mDummyThum;

	private Integer mTotalPage;
	
	public PdfThumbnailProvider(Context context, FoxitPdfCore foxitPdfCore, long contentId, boolean isNormalSize) {
		mContext = context;
		mFoxitPdfCore = foxitPdfCore;
        mContentId = contentId;
		configureSize(isNormalSize);
	}

	public PdfThumbnailProvider(Context context, long contentId, boolean isNormalSize) throws IOException {
		mContext = context;
        mContentId = contentId;
		String contentDir;
		try {
			contentDir = ContentFileExtractor.getInstance().getContentCacheDirWithExtract(contentId);
		} catch (Exception e) {
			throw new ABVRuntimeException("getJsonCopyFile failed. contentId=" + contentId, e);
		}
		if (contentDir == null) {
			throw new ABVRuntimeException("content not found. contentId=" + contentId);
		}
		
		ContentJSON contentJSON = mContentLogic.getContentInfoJson(contentDir, contentId);
		if (contentJSON == null) {
			throw new ABVRuntimeException("content json not found. contentId=" + contentId);
		}
		
		String fileName = contentJSON.getPdfFileName();
		String filepath = contentDir + "/" + fileName;
		File file = new File(filepath);
		Logger.v(TAG, "pdf file=%s", filepath);
		if (!file.exists()) {
			throw new ABVRuntimeException("pdf file not found. contentId=" + contentId);
		}
		try {
			mFoxitPdfCore = new FoxitPdfCore(context, filepath);
			boolean isExistPassWord = mFoxitPdfCore.loadPDFDoc(null);
			if (isExistPassWord) {
				// PDFパスワードあり
				DownloadedContentInfoJSON json = ContentFileUtil.getDownloadedContentInfoJSON(contentId);
				if (json.pdfPassword == null) {
					// エラー
					throw new ABVRuntimeException("authenticatePassword failed. contentId=" + contentId);
				}
				//TODO パスワードの認証失敗のエラーキャッチ
				mFoxitPdfCore.loadPDFDoc(json.pdfPassword.getBytes());
			}
			
			mTotalPage = mFoxitPdfCore.countPages(); // これをしておかないと後で取得ページがマイナスになる
			PointF p = mFoxitPdfCore.getPageSize(0);
			isLandscape = p.x > p.y;
		} catch (Exception e) {
			throw new ABVRuntimeException("mFoxitPdfCore failed. filepath=" + filepath);
		}
		
		configureSize(isNormalSize);
	}

	public void setIsLandscape(Boolean isLandscape) {
		this.isLandscape = isLandscape;
	}

	public void setPdfImageProvider(PdfImageProvider pdfImageProvider) {
		this.pdfImageProvider = pdfImageProvider;
	}
	
	/**
	 * 端末のサイズに合わせて、サムネイルのサイズ補正をこなう
	 * 
	 * @param isNormalSize
	 */
	private void configureSize(boolean isNormalSize) {
		float ratio = getRatio(isNormalSize);
		landHeightS *= ratio;
		landWidthS  *= ratio;
		portHeightS *= ratio;
		portWidthS *= ratio;

		landHeightM *= ratio;
		landWidthM *= ratio;
		portHeightM *= ratio;
		portWidthM *= ratio;

		landHeightL *= ratio;
		landWidthL *= ratio;
		portHeightL *= ratio;
		portWidthL *= ratio;
	}

	public float getRatio(boolean isNormalSize) {
		return (isNormalSize? ThumbnailSeekBarLayout.NORMAL_HEIGHT: ThumbnailSeekBarLayout.LARGE_HEIGHT) * mContext.getResources().getDisplayMetrics().density / ThumbnailSeekBarLayout.LARGE_HEIGHT;
	}

	public Bitmap getThumbnail(final int page, boolean isSmall) throws IOException {
		Logger.v(TAG, "getThumbnail page=%d", page);
		
		int width;
		int height;
		if (isSmall) {
			width = isLandscape? landWidthS : portWidthS;
			height = isLandscape? landHeightS: portHeightS;
		}
		else {
			width = isLandscape? landWidthL: portWidthL;
			height = isLandscape? landHeightL: portHeightL;
		}

		if (mFoxitPdfCore == null) {
			if (mDummyThum == null) {
				mDummyThum = createDummyThum(width, height, true);
			}
			return mDummyThum;
		}

		// 総ページ数を超えている場合、イメージなしの画像を返す
		if (mTotalPage == null) {
			try {
				mTotalPage = mFoxitPdfCore.countPages();
			} catch (PDFException e) {
				Logger.e(TAG, "FoxitPdfCore.countPages failed. ", e);
			}
		}
		if (mTotalPage < page + 1) {
			return BitmapUtil.getResizedBitmapResource(mContext.getResources(), R.drawable.no_image, width, height, Config.RGB_565, false);
		}

		if (isLandscape == null) {
			try {
				PointF p = mFoxitPdfCore.getPageSize(0);
				isLandscape = p.x > p.y;
			} catch (PDFException e) {
				Logger.e(TAG, "FoxitPdfCore.getPageSize failed. ", e);
			}
		}

		String thumPath = null;
		if (outputFile) {
			thumPath = ContentFileUtil.getPdfThumbnailPath(mContentId, page, (isSmall? ContentFileUtil.SIZE_S: ContentFileUtil.SIZE_L));
			Logger.v(TAG, "ThumPath=%s", thumPath);
			File file = new File(thumPath);
			if (file.exists()) {
				return BitmapFactory.decodeFile(thumPath, null);
			}
		}

		Bitmap bitmap = null;
		try {
			if (pdfImageProvider != null) {
				pdfImageProvider.setPauseTask(true);
			}
			bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
			bitmap = mFoxitPdfCore.drawPage(page, width, height, 0, 0, width, height);
		} finally {
			if (pdfImageProvider != null) {
				pdfImageProvider.setPauseTask(false);
			}
		}
		
		if (outputFile) {
			FileOutputStream output = null;
			try {
                if (thumPath != null) {
                    output = new FileOutputStream(thumPath);
                }
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
			}
			finally {
				if (output != null) {
					try {
						output.close();
					} catch (IOException e) {}
				}
			}
		}

		return bitmap;
	}
	
	public Bitmap createDummyThum(int width, int height, boolean isWhite) {
		Bitmap dummyThum = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(dummyThum);
		Paint paint = new Paint();
		if (isWhite) {
			paint.setColor(Color.WHITE);
		}
		else {
			paint.setAlpha(0);
		}
		canvas.drawRect(new RectF(0, 0, width, height), paint);
		return dummyThum;
	}

	public void close() {
		if (mFoxitPdfCore != null) {
			mFoxitPdfCore.releaseDoc();
		}
	}

}
