package jp.agentec.abook.abv.ui.home.helper;

import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.os.AsyncTask;
import android.util.Base64;
import android.widget.Toast;

import org.json.adf.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import jp.agentec.abook.abv.bl.common.ABVEnvironment;
import jp.agentec.abook.abv.bl.common.Callback;
import jp.agentec.abook.abv.bl.common.CommonExecutor;
import jp.agentec.abook.abv.bl.common.Constant;
import jp.agentec.abook.abv.bl.common.constant.ABookKeys;
import jp.agentec.abook.abv.bl.common.exception.ABVExceptionCode;
import jp.agentec.abook.abv.bl.common.exception.AcmsException;
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.OperationDao;
import jp.agentec.abook.abv.bl.data.dao.TaskReportDao;
import jp.agentec.abook.abv.bl.dto.OperationDto;
import jp.agentec.abook.abv.bl.dto.OperationTaskDto;
import jp.agentec.abook.abv.bl.dto.TaskDto;
import jp.agentec.abook.abv.bl.dto.TaskReportDto;
import jp.agentec.abook.abv.bl.logic.AbstractLogic;
import jp.agentec.abook.abv.bl.logic.OperationLogic;
import jp.agentec.abook.abv.launcher.android.R;
import jp.agentec.abook.abv.ui.common.activity.ABVContentViewActivity;
import jp.agentec.abook.abv.ui.common.appinfo.AppDefType;
import jp.agentec.abook.abv.ui.common.constant.ErrorMessage;
import jp.agentec.abook.abv.ui.common.util.PatternStringUtil;
import jp.agentec.abook.abv.ui.common.util.ABVToastUtil;
import jp.agentec.adf.util.DateTimeFormat;
import jp.agentec.adf.util.DateTimeUtil;
import jp.agentec.adf.util.FileUtil;
import jp.agentec.adf.util.StringUtil;

import static jp.agentec.abook.abv.bl.acms.client.json.OperationDataJSON.ReportStartDate;
import static jp.agentec.abook.abv.bl.acms.client.json.OperationDataJSON.TaskReportId;
import static jp.agentec.abook.abv.cl.util.PreferenceUtil.getUserPref;

/**
 * Created by leej on 2018/08/31.
 */

public class ABookCheckWebViewHelper extends ABookHelper {

    private static final String TAG = ABookCheckWebViewHelper.class.getSimpleName();

    private static ABookCheckWebViewHelper panoCheckViewHelper = null;
    private OperationLogic mOperationLogic = AbstractLogic.getLogic(OperationLogic.class);
    private Callback mFinishCallback;
    public static synchronized ABookCheckWebViewHelper getInstance() {
        if (panoCheckViewHelper == null) {
            panoCheckViewHelper = new ABookCheckWebViewHelper();
        }
        return panoCheckViewHelper;
    }

    /**
     * parameterによって処理を分ける
     *
     * @param context ABVContentViewActivity
     * @param cmd コマンド
     * @param taskKey タスクキー
     * @param enableReportHistory　履歴を残すかどうか
     * @param param パラメータ
     * @param operationId プロジェクトID
     * @param contentPath 添付資料のパス
     * @param reportType 報告タイプ
     * @param finishCallback 最後に呼ぶコールバック
     * @param taskReportLevel 作業の報告レベル
     */
    public void doABookCheckParam(ABVContentViewActivity context, String cmd, String taskKey, int enableReportHistory, Map<String, String> param, long operationId, String contentPath, long contentId, int reportType, Callback finishCallback, int taskReportLevel) throws IOException {
        int taskReportSendId = 0;
        mFinishCallback = finishCallback;

        // ActivityであるClassからCheckOZDViewActivityを確認してContextの値を変更する。
        if (ActivityHandlingHelper.getInstance().searchOzdActivityStack()) {
            context = (ABVContentViewActivity) ActivityHandlingHelper.getInstance().selectedOzdAtivityContext();
        }

        switch (cmd) {
            case ABookKeys.CMD_INSERT_TASK_REPORT:
            case ABookKeys.CMD_UPDATE_TASK_REPORT: {
                // もとから作業中だったかを調べる
                TaskReportDao taskReportDao = AbstractDao.getDao(TaskReportDao.class);
                int reportId = Integer.parseInt(String.valueOf(getOrZero(param, TaskReportId)));
                String startDate = getOrNull(param, ReportStartDate);
                boolean isLocalSaved = taskReportDao.isLocalSaved(taskKey, reportId, startDate);
                boolean isCompleted = taskReportDao.isCompleted(taskKey, reportId, startDate);
                boolean isWorking = taskReportDao.isWorking(taskKey, reportId, startDate);
                // 報告書の更新
                insertOrUpdateTaskReport(taskKey, enableReportHistory, operationId, contentId, param, contentPath, reportType, taskReportLevel, false);
                copyTaskAttachedMovie(operationId, contentId, taskKey, taskReportLevel);
                sendTaskData(context, operationId, taskKey, taskReportLevel);
                // 作業ステータスのカウントを変える todo:要リファクタリング(直すのはともかく動作確認する時間が惜しい)
                OperationDao operationDao = AbstractDao.getDao(OperationDao.class);
                if (isLocalSaved) {
                    operationDao.coutUpCompletedFromWorking(operationId);
                } else if (! isCompleted) {
                    boolean nowWorking = taskReportDao.isWorking(taskKey, reportId, startDate);
                    if (!isWorking && nowWorking) {
                        operationDao.countUpWorking(operationId);
                    } else {
                        operationDao.countUpCompleted(operationId);
                    }
                }
                break;
            }
            case ABookKeys.CMD_LOCAL_SAVE_TASK_REPORT:  // 一時保存
                // もとから作業中だったかを調べる
                TaskReportDao taskReportDao = AbstractDao.getDao(TaskReportDao.class);
                int rportId = Integer.parseInt(String.valueOf(getOrZero(param, TaskReportId)));
                String startDate = getOrNull(param, ReportStartDate);
                boolean isLocalSaved = taskReportDao.isLocalSaved(taskKey, rportId, startDate);
                // 報告書の更新
                insertOrUpdateTaskReport(taskKey, enableReportHistory, operationId, contentId, param, contentPath, reportType, taskReportLevel, true);
                copyTaskAttachedMovie(operationId, contentId, taskKey, taskReportLevel);
                ABVToastUtil.showMakeText(context, R.string.msg_temp_save_result, Toast.LENGTH_SHORT);
                // 作業ステータスのカウントを変える
                if (! isLocalSaved) {
                    OperationDao operationDao = AbstractDao.getDao(OperationDao.class);
                    operationDao.countUpWorking(operationId);
                }
                mFinishCallback.callback(false);
                break;
            case ABookKeys.CMD_DELETE_TASK_REPORT: {
                int taskReportId = 0;
                String reportStartDate = "";
                boolean sendTaskReportDataFlg = false;

                if (reportType == Constant.ReportType.RoutineTask) {
                    taskReportId = Integer.valueOf(param.get(ABookKeys.TASK_REPORT_ID));
                    reportStartDate = param.get(ABookKeys.REPORT_START_DATE).replace("T", " ").replace("Z", "");
                    mOperationLogic.deleteRoutineTaskReport(operationId, contentId, taskKey, taskReportId, reportStartDate);
                    mOperationLogic.createJsonForOperationContent(operationId, contentPath, true);
                    copyRoutineTaskReportAttachedMovie(operationId, contentId, taskKey, taskReportId, reportStartDate);
                } else {
                    mOperationLogic.deleteTaskReport(operationId, contentId, taskKey, taskReportLevel);
                    mOperationLogic.createJsonForOperationContent(operationId, contentPath, false);
                    copyTaskAttachedMovie(operationId, contentId, taskKey, taskReportLevel);
                }

                if (enableReportHistory == Constant.EnableReportHistory.Invalid) {
                    taskReportSendId = mOperationLogic.getLastTaskReportSendId(taskKey);
                    mOperationLogic.updateTaskReportSend(taskKey, taskReportId, reportStartDate, null, true);
                    deleteReportTaskSendFiles(operationId, taskKey, taskReportSendId, taskReportLevel);
                } else if (enableReportHistory == Constant.EnableReportHistory.Enable) {
                    mOperationLogic.insertTaskReportSend(taskKey, taskReportId, reportStartDate, null, true, false);
                }

                sendTaskData(context, operationId, taskKey, taskReportLevel);

                break;
            }
            case ABookKeys.CMD_MOVE_HOT_SPOT:
                mOperationLogic.updateTaskHotspot(taskKey, param);
                mOperationLogic.createHopSpotJson(operationId, contentPath);
                break;
            case ABookKeys.CMD_CANCEL_TASK_REPORT:
            case ABookKeys.CMD_CHANGE_TASK_REPORT:      // 報告・報告（回答）の切り替え　コールバック時は、何もしない
                FileUtil.delete(ABVEnvironment.getInstance().getTempTaskDirPath(contentId, taskKey));
                mFinishCallback.callback(false);
                break;
        }
    }

    /**
     * 作業報告・指示データ送信処理(共通)
     * @param context ABVContentViewActivity
     * @param operationId プロジェクトID
     * @param taskKey タスクキー
     */
    private void sendTaskData(final ABVContentViewActivity context,  final long operationId, final String taskKey, final int taskReportLevel) {
        // TODO 以下の処理見直し
        // ネットワーク通信チェック
        if (!ABVEnvironment.getInstance().networkAdapter.isNetworkConnected()) {
            mFinishCallback.callback(false);
            return;
        }

        final Callback progressCallback = new Callback() {
            @Override
            public Object callback(Object ret) {
                final int progress = (int)ret;
                context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        context.progressDialogHorizontal.setProgress(context.progressDialogHorizontal.getProgress() + progress);
                    }
                });
                return null;
            }
        };

        // リソースパターンの適用
        context.showProgressView(PatternStringUtil.patternToString(context,
                                    R.string.synchronizing,
                                    getUserPref(context, AppDefType.UserPrefKey.RESOURCE_PATTERN_TYPE, 0)));
        CommonExecutor.execute(new Runnable() {
            @Override
            public void run() {
                OperationDto operationDto = mOperationLogic.getOperation(operationId);
                boolean isError = false;

                try {
                    mOperationLogic.updateSyncOperation(operationId, true);
                    mOperationLogic.sendTaskReportSendData(operationId, taskKey, taskReportLevel, progressCallback);
                } catch (AcmsException ex) {
                    //noinspection EnumSwitchStatementWhichMissesCases
                    switch (ex.getCode()) {
                        case P_E_ACMS_P003:
                            // リソースパターンを適用
                            context.showSimpleAlertDialog(R.string.app_name, PatternStringUtil.patternToInt(context,
                                    R.string.P003,
                                    getUserPref(context, AppDefType.UserPrefKey.RESOURCE_PATTERN_TYPE, 0)));
                            break;
                        case P_E_ACMS_P004:
                            context.showSimpleAlertDialog(R.string.app_name, PatternStringUtil.patternToInt(context, R.string.P004, getUserPref(context, AppDefType.UserPrefKey.RESOURCE_PATTERN_TYPE, 0)));
                            break;
                        case P_E_ACMS_P005:
                            context.showSimpleAlertDialog(PatternStringUtil.patternToInt(context,
                                    R.string.app_name,
                                    getUserPref(context, AppDefType.UserPrefKey.RESOURCE_PATTERN_TYPE, 0)), PatternStringUtil.patternToInt(context,
                                    R.string.P005,
                                    getUserPref(context, AppDefType.UserPrefKey.RESOURCE_PATTERN_TYPE, 0)));
                            break;
                        case P_E_ACMS_P006:
                            context.showSimpleAlertDialog(R.string.app_name, R.string.P006);
                            break;
                        default:
                            context.handleErrorMessageToast(ErrorMessage.getErrorCode(ex));
                            break;
                    }
                    Logger.e(TAG, "sendTaskData", ex);
                    isError = true;
                } catch (Exception e) {
                    Logger.e(TAG, e);
                    context.handleErrorMessageToast(ABVExceptionCode.S_E_ACMS_0001);
                    isError = true;
                } finally {
                    mFinishCallback.callback(isError);
                    context.closeProgressPopup();
                }
            }
        });
    }

    public void doABookCheckParamPdf(long operationId, OperationTaskDto operationTaskDto, String contentPath) {
        try {
            mOperationLogic.updateTaskHotspot(operationTaskDto.taskKey, operationTaskDto.pdfX, operationTaskDto.pdfY, Constant.TaskReportLevel.ReportType);
            mOperationLogic.createHopSpotJson(operationId, contentPath);

        } catch(IOException e){
            e.printStackTrace();
        }
    }

    public void decodeToImage(String imageString, String outputPath) throws IOException {
        // ファイルがある場合のみ、削除
        FileUtil.delete(outputPath);
        // ディレクトリがない場合のみ、作成
        FileUtil.createParentDirectory(outputPath);
        String[] splitList = imageString.split(",");
        // ,でsplitした一番最初を除外する
        String imageString2 = imageString.replace(splitList[0], "");
        byte[] decodedByte = Base64.decode(imageString2, 0);
        FileOutputStream fos;
        fos = new FileOutputStream(outputPath);
        fos.write(decodedByte);

        fos.close();
    }

    /**
     * ビットマップをイメージファイルに変換
     * @param rotationAngle
     * @param photoFilePath
     * @param path
     * @return
     * @throws IOException
     */
    public File rotateBitmapToImageFile(int rotationAngle, String photoFilePath, String path) throws IOException {

        FileUtil.createNewDirectory(path);

        BitmapFactory.Options bounds = new BitmapFactory.Options();
        bounds.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(photoFilePath, bounds);
        BitmapFactory.Options opts = new BitmapFactory.Options();
        Bitmap originalBtimap = BitmapFactory.decodeFile(photoFilePath, opts);

        if (originalBtimap == null) {
            return null;
        }
        Logger.d(TAG, "originalBtimap.getWidth() = " + originalBtimap.getWidth() + "originalBtimap.getHeight() = " + originalBtimap.getHeight());
        Matrix matrix = new Matrix();
        matrix.setRotate(rotationAngle, (float) originalBtimap.getWidth() / 2, (float) originalBtimap.getHeight() / 2);
        Bitmap rotatedBitmap = Bitmap.createBitmap(originalBtimap, 0, 0, bounds.outWidth, bounds.outHeight, matrix, true);
        File file;
        try {
            // 日付でファイル名を作成　
            Date date = new Date();
            SimpleDateFormat fileName = new SimpleDateFormat("yyyyMMdd_HHmmss");
            // 保存処理開始
            file = new File(path + "/" + fileName.format(date) + ".jpg");
            FileOutputStream fos = new FileOutputStream(file);
            // jpegで保存
            rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            // 保存処理終了
            fos.close();

        } catch (Exception e) {
            Logger.e(TAG, e);
            throw e;
        }
        return file;
    }

    /**
     *
     * @param taskKey
     * @param enableReportHistory
     * @param operationId
     * @param contentId
     * @param param
     * @param contentPath
     * @param reportType
     * @param taskReportLevel
     * @throws IOException
     */
    private void insertOrUpdateTaskReport(String taskKey, int enableReportHistory, long operationId, long contentId, Map<String, String> param, String contentPath, int reportType, int taskReportLevel, boolean localSavedFlg) throws IOException {
        int taskReportSendId = 0;
        boolean attachedChangeFlag = param.get(ABookKeys.ATTACHED_CHANGE_FLAG).equals("1") ? true : false;
        String taskReport = param.get(ABookKeys.TASK_REPORT);
        JSONObject taskReportJson = new JSONObject(taskReport);
        int taskReportId = 0;
        String reportStartDate = "";

        if (reportType == Constant.ReportType.RoutineTask) {
            taskReportId = Integer.valueOf(param.get(ABookKeys.TASK_REPORT_ID));
            reportStartDate = param.get(ABookKeys.REPORT_START_DATE);
            reportStartDate = reportStartDate.replace("T", " ");

            TaskReportDto taskReportDto = mOperationLogic.getRoutineTaskReportUtc(taskKey, taskReportId, reportStartDate);
            taskReportDto.jsonData = taskReport;
            mOperationLogic.updateRoutineTaskReport(operationId, contentId, taskReportDto, attachedChangeFlag, localSavedFlg ? false : true, localSavedFlg);

            mOperationLogic.createJsonForOperationContent(operationId, contentPath, true);
            copyRoutineTaskReportAttachedMovie(operationId, contentId, taskKey, taskReportId, reportStartDate);
        } else {

            String hotSpotInfo = param.containsKey(ABookKeys.HOT_SPOT) ? param.get(ABookKeys.HOT_SPOT) : null;
            // 報告情報のjson取得後、登録・更新時に使用
            JSONObject taskJson = null;
            if (taskReportJson.has("task")) {
                taskJson = taskReportJson.getJSONObject("task");
            }
            // task登録・更新処理
            mOperationLogic.registTaskData(taskKey, operationId, hotSpotInfo, taskJson);


            TaskReportDto taskReportDto = mOperationLogic.getTaskReport(taskKey, taskReportLevel);
            int taskStatus = taskReportDto != null ? taskReportDto.taskStatus : 0;

            if (localSavedFlg) {
                //  一時保存の場合、q_3_???の値でtaskStatusを取り出す
                Iterator<String> keys = taskJson.keys();
                while (keys.hasNext()) {
                    String key = keys.next();
                    if (key.startsWith("q_3_")) {
                        taskStatus = taskJson.getInt(key);
                    }
                }
            }

            if (taskReportDto != null) {
                // 更新
                mOperationLogic.updateTaskReport(
                        taskReportDto.taskKey,
                        operationId,
                        contentId,
                        taskReportLevel,
                        Constant.EnableEditReport.YES,
                        taskReportJson,
                        null,
                        attachedChangeFlag,
                        localSavedFlg ? false : true,
                        localSavedFlg,
                        taskReportDto.getSendBackInfo(),
                        taskReportDto.getLockInfo(),
                        taskStatus
                );
            } else {
                // 登録
                mOperationLogic.insertTaskReport(
                        taskKey,
                        operationId,
                        contentId,
                        taskReportLevel,
                        Constant.EnableEditReport.YES,
                        taskReportJson,
                        null,
                        attachedChangeFlag,
                        localSavedFlg ? false : true,
                        localSavedFlg,
                        null,
                        null,
                        taskStatus
                );
            }
            mOperationLogic.createJsonForOperationContent(operationId, contentPath, false);
            copyTaskAttachedMovie(operationId, contentId, taskKey, taskReportLevel);
        }

        if (!localSavedFlg) {
            if (enableReportHistory == Constant.EnableReportHistory.Invalid) {
                //データ無い場合は中でinsertされる
                taskReportSendId = mOperationLogic.updateTaskReportSend(taskKey, taskReportId, reportStartDate, taskReportJson, false);
            } else {
                taskReportSendId = mOperationLogic.insertTaskReportSend(taskKey, taskReportId, reportStartDate, taskReportJson, false, false);
            }
            // #32926 作業報告画面改善 start
            copyReportTaskSendFiles(operationId, taskKey, taskReportSendId, reportType == Constant.ReportType.RoutineTask, taskReportId, reportStartDate, taskReportLevel);
            // #32926 作業報告画面改善 end
        }
    }

    // xwalkで動画ファイルにアクセスするため、../files/..の以下のパスのディレクトりを../cache/..以下のパスに変更
    public void allCopyTaskAttachedMovieFileToCache(long operationId, long contentId, OperationDto operationDto) {
        try {
            List<TaskDto> taskDtoList = mOperationLogic.getOperationTask(operationId);
            for (TaskDto taskDto : taskDtoList) {
                List<TaskReportDto> taskReportDtoList = mOperationLogic.getTaskReportByTaskKey(taskDto.taskKey);
                for (TaskReportDto taskReportDto : taskReportDtoList) {
                    if (operationDto.reportType == Constant.ReportType.RoutineTask) {
                        copyRoutineTaskReportAttachedMovie(operationId, contentId, taskReportDto.taskKey, taskReportDto.taskReportId, taskReportDto.reportStartDate);
                    } else {
                        copyTaskAttachedMovie(operationId, contentId, taskDto.taskKey, taskReportDto.taskReportLevel);
                    }
                }

            }
        } catch (IOException e) {
            Logger.e(TAG, "fileCopyToCacheAttachedDir error. ", e);
        }
    }

    /**
     * 定期点検
     * /.../files/ABook/operation/{operationId}/{taskKey}/report/{taskReportId}/{reportStartDate}/*.(mov,mp4)を
     * /.../cache/{contentId}/attachedMovie/{taskKey}/report/{taskReportId}/{reportStartDate}/*.(mov,mp4)にコピー
     * @param operationId
     * @param contentId
     * @param taskKey
     * @param taskReportId
     * @param objReportStartDate
     * @throws IOException
     */
    public void copyRoutineTaskReportAttachedMovie(long operationId, long contentId, String taskKey, int taskReportId, Object objReportStartDate) throws IOException {
        String reportStartDate;
        if (objReportStartDate instanceof String) {
            reportStartDate = DateTimeUtil.toString_yyyyMMddHHmmss_none(DateTimeUtil.toDate((String)objReportStartDate, DateTimeFormat.yyyyMMddHHmmss_hyphen));
        } else if (objReportStartDate instanceof Date) {
            reportStartDate = DateTimeUtil.toString_yyyyMMddHHmmss_none((Date)objReportStartDate);
        } else {
            return;
        }

        String taskKeyPath = ABVEnvironment.getInstance().getRoutineTaskReportDirFilePath(operationId, taskKey, taskReportId, reportStartDate);
        File taskKeyFile = new File(taskKeyPath);

        // 作業報告書の添付ファイル(mp4,mov拡張子のみ)コピー
        if (taskKeyFile.exists()) {
            String attachedMoviesFilePath = ABVEnvironment.getInstance().getAttachedRoutineTaskReportDirPath(contentId, taskKey, taskReportId, reportStartDate);
            FileUtil.delete(attachedMoviesFilePath);
            FileUtil.createNewDirectory(attachedMoviesFilePath);
            for (String taskAttachedFile : taskKeyFile.list()) {
                if (StringUtil.endsWithAny(taskAttachedFile.toLowerCase(), "mov", "mp4")) {
                    FileUtil.copy(taskKeyPath + "/" + taskAttachedFile, attachedMoviesFilePath + "/" + taskAttachedFile, true);
                }
            }
        }
    }

    /**
     * /.../files/ABook/operation/{operationId}/{taskKey}/{taskType}/{taskReportLevel}/*.(mov,mp4)を
     * /.../cache/{contentId}/attachedMovie/{taskKey}/{taskType}/{taskReportLevel}/*.(mov,mp4)にコピー
     *
     * @param operationId
     * @param contentId
     */
    public void copyTaskAttachedMovie(long operationId, long contentId, String taskKey, int taskReportLevel) throws IOException {
        // 作業指示書の添付ファイル(mp4,mov拡張子のみ)コピー
        String taskKeyPath = ABVEnvironment.getInstance().getOperationTaskReportLevelDirPath(operationId, taskKey, taskReportLevel);
        File taskKeyFile = new File(taskKeyPath);
        if (taskKeyFile.exists()) {
            String attachedMoviesFilePath = ABVEnvironment.getInstance().getAttachedDirectionOrReportDirPath(contentId, taskKey, taskReportLevel);
            // 存在しない場合は無視する
            FileUtil.delete(attachedMoviesFilePath);
            
            FileUtil.createNewDirectory(attachedMoviesFilePath);
            for (String taskAttachedFile : taskKeyFile.list()) {
                if (StringUtil.endsWithAny(taskAttachedFile.toLowerCase(), "mov", "mp4")) {
                    FileUtil.copy(taskKeyPath + "/" + taskAttachedFile, attachedMoviesFilePath + "/" + taskAttachedFile, true);
                }
            }
        }
    }

    /**
     * 作業報告送信ファイルコピー
     * @param operationId
     * @param taskKey
     * @param taskReportSendId
     * @param routineTaskReportFlg
     * @param taskReportId
     * @param reportStartDate
     * @throws IOException
     */
    public void copyReportTaskSendFiles(final long operationId, final String taskKey, final int taskReportSendId, boolean routineTaskReportFlg, int taskReportId, String reportStartDate, int taskReportLevel) throws IOException {
        String taskAttachedPath;
        Date dReportStartDate;
        String sReportStartDate = "";

        if (routineTaskReportFlg) {
            dReportStartDate = DateTimeUtil.toDate(reportStartDate, DateTimeFormat.yyyyMMddHHmmss_hyphen);
            sReportStartDate = DateTimeUtil.toString_yyyyMMddHHmmss_none(dReportStartDate);
            taskAttachedPath = ABVEnvironment.getInstance().getRoutineTaskReportDirFilePath(operationId, taskKey, taskReportId, sReportStartDate);
        } else {
            // #32926 作業報告画面改善 start
            taskAttachedPath = ABVEnvironment.getInstance().getOperationTaskReportLevelDirPath(operationId, taskKey, taskReportLevel);
            // #32926 作業報告画面改善 end
        }
        File taskAttachedFiles = new File(taskAttachedPath);

        if (taskAttachedFiles.exists()) {
            String taskReportSendPath = ABVEnvironment.getInstance().getOperationTaskReportSendDirFilePath(operationId, taskKey, taskReportSendId);

            FileUtil.delete(taskReportSendPath);
            FileUtil.createNewDirectory(taskReportSendPath);

            for (String taskAttachedFile : taskAttachedFiles.list()) {
                if (!taskAttachedFile.equals(ABVEnvironment.getInstance().REPORT_SEND)) {
                    FileUtil.copy(taskAttachedPath + "/" + taskAttachedFile, taskReportSendPath + "/" + taskAttachedFile, true);
                }
            }
        }
    }

    /**
     * 作業報告送信ファイル削除
     * @param operationId
     * @param taskKey
     * @param taskReportSendId
     * @throws IOException
     */
    public void deleteReportTaskSendFiles(final long operationId, final String taskKey, final int taskReportSendId, final int taskReportLevel) throws IOException {
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                try {
                    String taskReportSendPath = ABVEnvironment.getInstance().getOperationTaskReportSendDirFilePath(operationId, taskKey, taskReportSendId);
                    FileUtil.delete(taskReportSendPath);
                } catch (Exception ex) {
                    Logger.e(String.format("%s.deleteReportTaskSendFiles(%d, %s)", TAG, operationId, taskKey), ex);
                }

                return null;
            }

            /*@Override
            protected void onPostExecute(Void v) {
                super.onPostExecute(v);
            }*/
        }.execute();
    }

    public String contentSchemeUriToFilePath(Cursor cursor) {
        String photoFilePath = null;
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                photoFilePath = cursor.getString(0);
            }
            cursor.close();
        }
        return photoFilePath;
    }

    public int rotateBitmapOrientation(String photoFilePath) throws IOException {
        ExifInterface exif = null;
        try {
            exif = new ExifInterface(photoFilePath);
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        }
        int rotationAngle = 0;
        String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
        int orientation = orientString != null ? Integer.parseInt(orientString) : ExifInterface.ORIENTATION_NORMAL;

        switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                rotationAngle = 90;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                rotationAngle = 180;
                break;

            case ExifInterface.ORIENTATION_ROTATE_270:
                rotationAngle = 270;
                break;

        }

        return rotationAngle;
    }

    private String getOrZero(Map<String, String> param, String key) {
        if (param.containsKey(key)) {
            return param.get(key);
        } else {
            return "0";
        }
    }

    private String getOrNull(Map<String, String> param, String key) {
        if (param.containsKey(key)) {
            return param.get(key);
        } else {
            return null;
        }
    }
}
