package jp.agentec.abook.abv.bl.logic;

import java.sql.Timestamp;
import java.util.List;
import java.util.Map;

import jp.agentec.abook.abv.bl.acms.client.json.content.ActionInfoJSON;
import jp.agentec.abook.abv.bl.acms.client.json.content.LocationJSON;
import jp.agentec.abook.abv.bl.acms.client.json.content.PageObjectJSON;
import jp.agentec.abook.abv.bl.common.exception.ABVException;
import jp.agentec.abook.abv.bl.common.log.Logger;
import jp.agentec.abook.abv.bl.common.util.JsonUtil;
import jp.agentec.abook.abv.bl.data.dao.AbstractDao;
import jp.agentec.abook.abv.bl.data.dao.ContentObjectLogDao;
import jp.agentec.abook.abv.bl.dto.ContentObjectLogDto;
import jp.agentec.adf.util.DateTimeFormat;
import jp.agentec.adf.util.DateTimeUtil;
import jp.agentec.adf.util.StringUtil;

import org.json.adf.JSONArray;
import org.json.adf.JSONObject;
public  class ContentObjectLogLogic extends AbstractLogic {
	private static final String TAG = "ContentObjectLogLogic";
	private ContentObjectLogDao contentObjectLogDao = AbstractDao.getDao(ContentObjectLogDao.class);

	/*package*/ ContentObjectLogLogic() {
	}

	/**
	 * ページ閲覧開始
	 * 
	 * @param contentId
	 * @param readingLogId
	 * @param pageObjectJSON
	 */
	public int insertContentObjectLog(long contentId, int readingLogId, PageObjectJSON pageObjectJSON, long resourceId) {
		ActionInfoJSON actionInfoJSON = pageObjectJSON.getActionInfo();
		LocationJSON locationJSON = pageObjectJSON.getLocation();

		ContentObjectLogDto dto = new ContentObjectLogDto();

		dto.objectLogId = contentObjectLogDao.getNewContentObjectLogId();
		dto.readingLogId = readingLogId;
		dto.actionDate = DateTimeUtil.getCurrentDate();
		dto.contentId = contentId;
		dto.pageNum = pageObjectJSON.getPageNumber();
		dto.objectId = actionInfoJSON.getObjectId();
		dto.resourceId = resourceId;
		dto.mediaType = pageObjectJSON.getMediaType();
		try {
			dto.actionType = JsonUtil.getInt(actionInfoJSON, "actionType");
		} catch (ABVException e) {
			dto.actionType = null;
//			Logger.e(getClass().getName(), "insertContentObjectLog error.", e); // ログなのでJSON関係のエラーは無視（オブジェクトが表示できていれば、ここに来ることはない）
		}
		dto.actionValue = getActionValue(actionInfoJSON);
		dto.actionTime = 0;

		// TODO later 必要あればタッチした詳細の座標情報に後々修正
		dto.locationX = locationJSON.getXDouble();
		dto.locationY = locationJSON.getYDouble();

		dto.locationHeight = locationJSON.getHeight();
		dto.locationWidth = locationJSON.getWidth();

		contentObjectLogDao.insertContentObjectLog(dto);

		return dto.objectLogId;
	}

	/**
	 * オブジェクトログ開始
	 *
	 * @param contentId
	 * @param readingLogId
	 * @param pageNo
	 * @param map
	 */
	public int insertContentObjectLog(long contentId, int readingLogId, int pageNo, Map<String, String> map) {
		ContentObjectLogDto dto = new ContentObjectLogDto();
		dto.objectLogId = contentObjectLogDao.getNewContentObjectLogId();
		dto.readingLogId = readingLogId;
		dto.actionDate = DateTimeUtil.getCurrentDate();
		dto.contentId = contentId;
		dto.pageNum = pageNo;
		dto.objectId = Long.parseLong(map.get("objectId"));
		if (!StringUtil.isNullOrEmpty(map.get("resourceId"))) {
			dto.resourceId = Long.parseLong(map.get("resourceId"));
		}
		dto.mediaType = Integer.parseInt(map.get("mediaType"));
		dto.actionType = Integer.parseInt(map.get("actionType"));
		dto.actionValue = map.get("actionValue");
		dto.actionTime = 0;
		dto.locationX = Double.parseDouble(map.get("locationX"));
		dto.locationY = Double.parseDouble(map.get("locationY"));
		dto.locationHeight = (int)Double.parseDouble(map.get("locationHeight"));
		dto.locationWidth = (int)Double.parseDouble(map.get("locationWidth"));
		dto.eventType = map.get("eventType");

		contentObjectLogDao.insertContentObjectLog(dto);
		return dto.objectLogId;
	}

	public void updateActionTime(int objectLogId, int actionTime){
		ContentObjectLogDto dto = contentObjectLogDao.getContentObjectLog(objectLogId);
		if (dto == null) {
			Logger.w(TAG, "ContentObjectLogDto not found. objectLogId=", objectLogId);
			return;
		}
		dto.actionTime = actionTime;
		contentObjectLogDao.updateContentObjectLog(dto);
	}

	private String getActionValue(ActionInfoJSON actionInfoJSON){
		String actionValue = null;
		
		Integer actionType = null;
		
		try {
			actionType = JsonUtil.getInt(actionInfoJSON, "actionType");
		} catch (ABVException e) {
//			Logger.e(getClass().getName(), "insertContentObjectLog error.", e); // ログなのでJSON関係のエラーは無視（オブジェクトが表示できていれば、ここに来ることはない）
		}
		if(actionType != null){
			switch (actionType) {
			case ActionInfoJSON.VIDEO_ACTION:
				actionValue = actionInfoJSON.getVideoFileName();
				break;
			case ActionInfoJSON.MUSIC_ACTION:
				actionValue = actionInfoJSON.getMusicFileName();
				break;
			case ActionInfoJSON.LINKURL_ACTION:
				actionValue = actionInfoJSON.getLinkUrl();
				break;
			case ActionInfoJSON.PREVIEW_ACTION:
				actionValue = getPreviewActionValue(actionInfoJSON);
				break;
			case ActionInfoJSON.JUMPPAGE_ACTION:
				actionValue =  "" + (actionInfoJSON.getJumpPage());
				break;
			case ActionInfoJSON.EMAIL_ACTION:
				actionValue = actionInfoJSON.getEmailAddress();
				break;
			case ActionInfoJSON.TRIGGER_ACTION:
				// なし
				break;
			case ActionInfoJSON.BALLOON_ACTION:
				// なし
				break;
			case ActionInfoJSON.HTML_ACTION:
				actionValue = actionInfoJSON.getHtml() + ".zip";
				break;
			case ActionInfoJSON.CONTENTLINK_ACTION:
				actionValue = "" + actionInfoJSON.getContentId();
				break;
			case ActionInfoJSON.ENQUETE_ACTION:
			case ActionInfoJSON.EXAM_ACTION:
			case ActionInfoJSON.QUIZ_ACTION:
				actionValue = actionInfoJSON.getEnquete() + ".zip";
				break;
			default:
				break;
			}
		}
		return actionValue;
	}

	private String getPreviewActionValue(ActionInfoJSON actionInfoJSON) {
		// プレビューの場合、リソースIDをカンマで連結
		Long[] resourceIds = actionInfoJSON.getResourceIds();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < resourceIds.length; i++) {
			sb.append(resourceIds[i]);
			if (i < resourceIds.length - 1) {
				sb.append(",");
			}
		}
		return sb.toString();
	}

	public JSONObject getContentObjectLogJson(long contentId, int readingLogId) {
		JSONObject json = null;
		List<ContentObjectLogDto> list = contentObjectLogDao.getContentObjectLogs(contentId, readingLogId);

		if (list.size() > 0) {
			json = new JSONObject();

			// csvのheader部
			JSONArray headerArray = new JSONArray();
			headerArray.put("actionDate");
			headerArray.put("contentId");
			headerArray.put("pageNo");
			headerArray.put("objectId");
			headerArray.put("resourceId");
			headerArray.put("mediaType");
			headerArray.put("actionType");
			headerArray.put("actionValue");
			headerArray.put("actionTime");
			headerArray.put("locationX");
			headerArray.put("locationY");
			headerArray.put("locationHeight");
			headerArray.put("locationWidth");
			headerArray.put("eventType");

			json.put("header", headerArray);

			JSONArray linesRootArray = new JSONArray();

			// csvのbody部
			for (ContentObjectLogDto dto : list) {
				JSONArray linesArray = new JSONArray();

				Timestamp actionDate = new Timestamp(dto.actionDate.getTime());
				linesArray.put(DateTimeUtil.toStringInTimeZone(actionDate, DateTimeFormat.yyyyMMddHHmmss_hyphen, "GMT") + ",GMT");

				linesArray.put(dto.contentId);

				// Androidは0からで管理しているので+1する
				linesArray.put(dto.pageNum + 1);
				linesArray.put(dto.objectId);

				if (dto.resourceId == -1) {
					linesArray.put("");
				} else {
					linesArray.put(dto.resourceId);
				}
				
				if (dto.mediaType == -1) {
					linesArray.put("");
				} else {
					linesArray.put(dto.mediaType);
				}

				if (dto.actionType == null) {
					linesArray.put("");
				} else {
					linesArray.put(dto.actionType);
				}

				if (dto.actionValue == null) {
					// nullの場合、空文字
					linesArray.put("");
				} else {
					linesArray.put(dto.actionValue);
				}

				linesArray.put(dto.actionTime);
				linesArray.put(dto.locationX);
				linesArray.put(dto.locationY);
				linesArray.put(dto.locationHeight);
				linesArray.put(dto.locationWidth);

				if (dto.eventType == null) {
					// nullの場合、空文字
					linesArray.put("");
				} else {
					linesArray.put(dto.eventType);
				}

				linesRootArray.put(linesArray);
			}
			json.put("lines", linesRootArray);
		}

		return json;
	}
}
