package jp.agentec.abook.abv.cl.helper;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;

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

import jp.agentec.abook.abv.bl.common.ABVEnvironment;
import jp.agentec.abook.abv.bl.common.log.Logger;
import jp.agentec.abook.abv.bl.data.dao.AbstractDao;
import jp.agentec.abook.abv.bl.data.dao.ContentDao;
import jp.agentec.abook.abv.bl.data.dao.ContentMarkingDao;
import jp.agentec.abook.abv.bl.dto.ContentDto;
import jp.agentec.abook.abv.bl.dto.ContentMarkingDto;
import jp.agentec.abook.abv.bl.logic.AbstractLogic;
import jp.agentec.abook.abv.bl.logic.MarkingLogic;
import jp.agentec.abook.abv.bl.websocket.MeetingManager;
import jp.agentec.abook.abv.cl.util.BitmapUtil;
import jp.agentec.adf.util.FileUtil;

/**
 * マーキングのファイル操作などをするサービスクラスです。
 * 
 * @author tauchi
 *
 */
public class ContentMarkingFileHelper {
	private final String EXTENSION = ".png";
	private ContentMarkingDao contentMarkingDao = AbstractDao.getDao(ContentMarkingDao.class);
	private MarkingLogic markingLogic = AbstractLogic.getLogic(MarkingLogic.class);
	private ContentDao contentDao = AbstractDao.getDao(ContentDao.class);
	private MeetingManager meetingManager;

	public ContentMarkingFileHelper() {
		meetingManager = MeetingManager.getInstance();
	}

	/**
	 * 指定したコンテンツの指定したページのマーキングファイルを読み込み返します。
	 * 
	 * @param contentId コンテンツID
	 * @param pageNum ページナンバー
	 * @return ロードされたビットマップ。なければnullを返します。
	 * @throws Exception
	 */
	public Bitmap getMarkingFile(long contentId, int pageNum) {

		String path;
		String fname;

		if(meetingManager.isConnected() && !meetingManager.isPaused()){
			// 遠隔連動中は別フォルダからファイルを読み取る
			path = ABVEnvironment.getInstance().getContentRemoteMarkingDirectoryPath(contentId, false);
			fname = path + File.separator + pageNum + EXTENSION;
		} else {
			path = ABVEnvironment.getInstance().getContentMarkingDirectoryPath(contentId, false);
			ContentMarkingDto dto = contentMarkingDao.getMarking(contentId, pageNum);
			if (dto == null) {
				return null;
			}
			fname = path + File.separator + dto.fileName;
		}
		File file = new File(fname);
		if (file.exists()) {
			return BitmapUtil.getBitmap(fname, Config.ARGB_4444);
		} else {
			return null;
		}
	}

	public File[] getMarkingFiles(long contentId) {
		String path = ABVEnvironment.getInstance().getContentMarkingDirectoryPath(contentId, false);
		File dir_path = new File(path);
		File[] fileList = null;
		if (dir_path.exists()) {
			fileList = dir_path.listFiles();
		}
		return fileList;
	}

	/**
	 * 指定したコンテンツの指定したページのマーキングファイルを保存します。
	 * 保存形式はpngです。
	 * 
	 * @param context Androidコンテキスト
	 * @param contentId コンテンツID
	 * @param pageNum ページナンバー
	 * @param src 保存するビットマップ
	 * @throws IOException 
	 * @throws Exception
	 */
	public void saveMarkingFile(Context context, long contentId, int pageNum, int width, int height, Bitmap src) throws IOException {
		boolean checkFlg = false;
		for (int i = 0; i < src.getHeight(); i++) {
			for (int j = 0; j < src.getWidth(); j++) {
				if (src.getPixel(j, i) != 0) {
					checkFlg = true;
					break;
				}
			}
			if (checkFlg) {
				break;
			}
		}
		Logger.d("비트맵 체크 ", "결과 값 : " + checkFlg);

		File fout;

		if (meetingManager.isConnected() && !meetingManager.isPaused()) {
			// 遠隔連動中は別フォルダにファイルを保存する
			fout = ABVEnvironment.getInstance().getContentRemoteMarkingDirectory(contentId, false);
		} else {
			fout = ABVEnvironment.getInstance().getContentMarkingDirectory(contentId, false);
		}

		String fileName = pageNum + EXTENSION;
		String outputFilePath = fout.getAbsolutePath() + File.separator + fileName;

        if (checkFlg) {
            //저장할 이미지.
            // 指定のサイズにリサイズして保存
            Bitmap bitmap = Bitmap.createScaledBitmap(src, width, height, false);
            fout.mkdirs();

            FileOutputStream out = null;
            try {
                out = new FileOutputStream(outputFilePath);
                bitmap.compress(CompressFormat.PNG, 1, out);
                out.flush();
                out.close();
            } finally {
                if (out != null) {
                    try {
                        out.close();
                    } catch (Exception e2) {
                    }
                }
            }

            if (!meetingManager.isConnected() || meetingManager.isPaused()) {
                markingLogic.insertUpdateContentMarking(contentId, pageNum, fileName);
            }
        } else {
            //빈 이미지. 해당 파일 있을 경우 이미지 삭제처리
            FileUtil.delete(outputFilePath);

            if (!meetingManager.isConnected() || meetingManager.isPaused()) {
                contentMarkingDao.deleteMarking(contentId, pageNum);
            }
        }
	}

	/**
	 * 指定したコンテンツのマーキングファイルを全て削除します。
	 * 
	 * @param contentId コンテンツID
	 * @throws Exception
	 */
	public void deleteMarkingFile(long contentId) throws Exception {
		File fout = ABVEnvironment.getInstance().getContentMarkingDirectory(contentId, false);
		FileUtil.deleteChilds(fout);
		contentMarkingDao.deleteMarking(contentId);
	}

	public void deleteRemoteMarkingFile(long contentId) {
		File fout = ABVEnvironment.getInstance().getContentRemoteMarkingDirectory(contentId, false);
		FileUtil.delete(fout);
	}

	/**
	 * コンテンツ間でマーキングをコピーします。
	 * 同じページにマーキングが存在する場合上書きします。
	 * 
	 * @param srcContentId コピー元コンテンツID
	 * @param dstContentId コピー先コンテンツID
	 * @throws IOException 
	 * @throws Exception
	 */
	public void copyMarkingFile(long srcContentId, long dstContentId) throws IOException {
		// コピー元
		List<ContentMarkingDto> srcMarkingDtoList = contentMarkingDao.getMarkingList(srcContentId);
		String srcDirPath = ABVEnvironment.getInstance().getContentMarkingDirectory(srcContentId, false).getAbsolutePath();

		// コピー先
		ContentDto dstContentDto = contentDao.getContent(dstContentId);
		String dstDirPath = ABVEnvironment.getInstance().getContentMarkingDirectory(dstContentId, false).getAbsolutePath();

		for (ContentMarkingDto srcMarkingDto : srcMarkingDtoList) {
			// ページを超えている場合コピーしない
			if (dstContentDto.allPageNum - 1 < srcMarkingDto.pageNum) {
				break;
			}
			FileUtil.copy(srcDirPath + File.separator + srcMarkingDto.fileName, dstDirPath + File.separator + srcMarkingDto.fileName, true);
			markingLogic.insertUpdateContentMarking(dstContentId, srcMarkingDto.pageNum, srcMarkingDto.fileName);
		}
	}

	/**
	 * 指定したコンテンツの指定したページの合成後マーキングファイルを保存します。
	 * 保存形式はpngです。
	 * 既存マーキングがある場合は会議中マーキングを合成後保存
	 * 既存マーキングがない場合は会議中マーキングをコピー
	 *
	 * @param contentId コンテンツID
	 * @param pageNum ページナンバー
	 * @throws IOException
	 */
	public void saveMarkingOnMeeting(long contentId, int pageNum) throws IOException {
		Bitmap remoteBmp = this.getContentRemoteMarkingFile(contentId, pageNum);
		if (remoteBmp == null) {
			return;
		}
		Bitmap markingBmp = this.getContentMarkingFile(contentId, pageNum);
		if (markingBmp != null) {
			saveComposedMarkingFile(contentId, pageNum);
		} else {
			copyRemoteMarkingFile(contentId, pageNum);
		}
	}

	/**
	 * 指定したコンテンツの指定したページの合成後マーキングファイルを保存します。
	 * 保存形式はpngです。
	 *
	 * @param contentId コンテンツID
	 * @param pageNum ページナンバー
	 * @throws IOException
	 */
	private void saveComposedMarkingFile(long contentId, int pageNum) throws IOException {
		File fout = ABVEnvironment.getInstance().getContentMarkingDirectory(contentId, false);

		String fileName = pageNum + EXTENSION;
		String outputFilePath = fout.getAbsolutePath() + File.separator + fileName;
		String remoteDirPath = ABVEnvironment.getInstance().getContentRemoteMarkingDirectoryPath(contentId, false);
		String remoteFilePath = remoteDirPath + File.separator + pageNum + EXTENSION;

		Bitmap bmp = null;
		FileOutputStream out = null;
		try {
			// ファイル合成
			bmp = composeBitmap(contentId, pageNum);

			// 合成前ファイルは削除
			FileUtil.delete(outputFilePath);
			// 合成後ファイルを保存
			out = new FileOutputStream(outputFilePath);
			bmp.compress(CompressFormat.PNG, 1, out);
			out.flush();

		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		} finally {
			if (bmp != null) {
				bmp.recycle();
			}
			if (out != null) {
				try {
					out.close();
				} catch (Exception e2) {
				}
			}
		}
	}

	/**
	 * 会議中マーキングをコピー後登録します。
	 * 保存形式はpngです。
	 *
	 * @param contentId コンテンツID
	 * @param pageNum ページナンバー
	 * @throws IOException
	 * @throws Exception
	 */
	private void copyRemoteMarkingFile(long contentId, int pageNum) throws IOException {
		String fileName = pageNum + EXTENSION;

		// コピー元
		String srcDirPath = ABVEnvironment.getInstance().getContentRemoteMarkingDirectory(contentId, false).getAbsolutePath();

		// コピー先
		String dstDirPath = ABVEnvironment.getInstance().getContentMarkingDirectory(contentId, false).getAbsolutePath();

		// ファイルコピー
		FileUtil.copy(srcDirPath + File.separator + fileName, dstDirPath + File.separator + fileName, true);
		// マーキングデータ登録
		markingLogic.insertUpdateContentMarking(contentId, pageNum, fileName);
	}

	/**
	 * Bitmapの画像データを合成する。
	 */
	private Bitmap composeBitmap(long contentId, int pageNum) {
		Bitmap currentBitmap = getContentMarkingFile(contentId, pageNum);
		Bitmap blendBitmap = getContentRemoteMarkingFile(contentId, pageNum);
		int width = currentBitmap.getWidth();
		int height = currentBitmap.getHeight();
		Bitmap new_bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(new_bitmap);
		canvas.drawBitmap(currentBitmap, 0, 0, (Paint)null); // image, x座標, y座標, Paintイタンス
		canvas.drawBitmap(blendBitmap, 0, 0, (Paint)null); // 画像合成

		return new_bitmap;
	}

	/**
	 * 指定したコンテンツの指定したページのマーキングファイルを読み込み返します。
	 *
	 * @param contentId コンテンツID
	 * @param pageNum ページナンバー
	 * @return ロードされたビットマップ。なければnullを返します。
	 * @throws Exception
	 */
	public Bitmap getContentMarkingFile(long contentId, int pageNum) {

		String path;
		String fname;

		path = ABVEnvironment.getInstance().getContentMarkingDirectoryPath(contentId, false);
		ContentMarkingDto dto = contentMarkingDao.getMarking(contentId, pageNum);
		if (dto == null) {
			return null;
		}
		fname = path + File.separator + dto.fileName;
		File file = new File(fname);
		if (file.exists()) {
			return BitmapUtil.getBitmap(fname, Config.ARGB_4444);
		} else {
			return null;
		}
	}

	/**
	 * 指定したコンテンツの指定したページの会議室でのマーキングファイルを読み込み返します。
	 *
	 * @param contentId コンテンツID
	 * @param pageNum ページナンバー
	 * @return ロードされたビットマップ。なければnullを返します。
	 * @throws Exception
	 */
	public Bitmap getContentRemoteMarkingFile(long contentId, int pageNum) {

		String path;
		String fname;

		// 遠隔連動中は別フォルダからファイルを読み取る
		path = ABVEnvironment.getInstance().getContentRemoteMarkingDirectoryPath(contentId, false);
		fname = path + File.separator + pageNum + EXTENSION;
		File file = new File(fname);
		if (file.exists()) {
			return BitmapUtil.getBitmap(fname, Config.ARGB_4444);
		} else {
			return null;
		}
	}


}
