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

import android.content.ClipData;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PointF;
import android.net.Uri;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.RelativeLayout;

import org.json.adf.JSONObject;

import java.util.List;

import jp.agentec.abook.abv.bl.common.Constant;
import jp.agentec.abook.abv.bl.common.constant.ABookKeys;
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.TaskDao;
import jp.agentec.abook.abv.bl.dto.OperationTaskDto;
import jp.agentec.abook.abv.bl.dto.TaskDto;
import jp.agentec.abook.abv.launcher.android.R;
import jp.agentec.abook.abv.ui.common.activity.ABVActivity;
import jp.agentec.abook.abv.ui.common.activity.ABVContentViewActivity;
import jp.agentec.abook.abv.ui.viewer.activity.ContentViewActivity;
import jp.agentec.adf.util.StringUtil;

/**
 * Created by seo-y on 2018/11/14.
 */

public class OperationTaskLayout extends RelativeLayout {
    private static final String TAG = "OperationTaskLayout";
    private static final String TEMP_TASK_KEY = "00000000-0000-0000-0000-000000000000";
    private static final String SCRIPT_SHOW_TASK_LIST = "javascript:CHK_P.updateTaskListForApp(%d)";//CHK.updateTaskListForApp(pageNum)
    private static final String SCRIPT_SHOW_TASK_REPORT = "javascript:CHK.showReportForm('%s')";//CHK.showTaskReportForm(name, taskKey, lookto)

    private static final int ICON_WIDTH = 32;
    private static final int ICON_HEIGHT = 32;

    private static final int CODE_WIDTH = 46;
    private static final int CODE_HEIGHT = 26;

    public static final int HALF_WIDTH = 340;
    public static final int COLOR_ORANGE = Color.rgb(255, 119, 0);
    public static final int COLOR_BLUE = Color.rgb(27, 27, 210);

    private static final int FINISHED_STATUS = 999;

    private WebView mWebView = null;

    public ZoomRelativeLayout currentLayout;
    public OperationTaskDto currentTaskDto;

    private ContentViewActivity mContext;
    private JsInf jsInf = new JsInf();

    private static TaskDao mTaskDao = AbstractDao.getDao(TaskDao.class);

    public OperationTaskLayout(final Context context, final long contentId, final String linkUrl, boolean isNormalSize) {
        super(context);
        mContext = (ContentViewActivity)context;

        if (isNormalSize) {
            setPadding(0, 130, 0, 0);
        }

        mWebView = new EnqueteWebView(context);
        mWebView.setVerticalScrollbarOverlay(true); // スクロールバー部分の隙間を消す
        mWebView.setWebContentsDebuggingEnabled(true); //デバッグモード（chromeからinspect可)
        mWebView.addJavascriptInterface(jsInf, "android");
        // //ブラウザの描画領域を対象としたイベントをフック
        WebSettings settings = mWebView.getSettings();
        settings.setSupportMultipleWindows(true); // 新しいウィンドウを開くイベントを取得する
        settings.setLoadsImagesAutomatically(true); // イメージを自動的にロードする
        settings.setBuiltInZoomControls(true); // ズーム機能を有効にする
        settings.setSupportZoom(true); // ズーム機能を有効にする
        settings.setJavaScriptEnabled(true); // JavaScriptを有効にする
        settings.setLoadWithOverviewMode(true); // 画面の横幅にページの横幅を合わせる
        settings.setUseWideViewPort(true); // 画面の横幅にページの横幅を合わせる
        //noinspection deprecation(API18から非推奨になった。無視)
        settings.setPluginState(WebSettings.PluginState.ON); // 「EventHub.removeMessages(int what = 107) is not supported before the WebViewCore is set up.」のエラー対応（あまり効果ない？）
        settings.setDomStorageEnabled(true); // WebStorage有効化
        settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
        // mWebView.loadDataWithBaseURL("", url2, "text/html", "UTF-8", "");
        settings.setAllowFileAccessFromFileURLs(true);  //Android7利用で警告ダイヤログ表示問題対応
        //ターゲットバージョン30以上からデフォルトがfalseに設定されている問題対応
        settings.setAllowFileAccess(true);

        mWebView.loadUrl(linkUrl);

        RelativeLayout.LayoutParams params = createParam(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
        params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        addView(mWebView, params);

        mWebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                ((ContentViewActivity)context).commonProgressChanged(newProgress);
            }

            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
                                             FileChooserParams fileChooserParams) {
                boolean result = false;
                if(fileChooserParams.getAcceptTypes()[0].toLowerCase().indexOf(ABookKeys.IMAGE) != -1) {
                    result = ((ABVActivity)context).startCameraIntent(((ABVContentViewActivity)context).ABOOK_CHECK_TASK_IMAGE, "Camera", ABookKeys.IMAGE, true);

                } else if(fileChooserParams.getAcceptTypes()[0].toLowerCase().indexOf(ABookKeys.VIDEO) != -1) {
                    result = ((ABVActivity)context).startCameraIntent(((ABVContentViewActivity)context).ABOOK_CHECK_TASK_VIDEO, "Video", ABookKeys.VIDEO, true);
                }

                if (result) {
                    if(((ContentViewActivity)context).mUploadMessage != null){
                        ((ContentViewActivity)context).mUploadMessage.onReceiveValue(null);
                    }
                    ((ContentViewActivity)context).mUploadMessage = filePathCallback;
                }
                Logger.i(TAG, "oepnFile acceptType : %s", fileChooserParams.getAcceptTypes()[0]);
                return result;
            }
        });

        mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                Logger.v(TAG, "shouldOverrideUrlLoading: %s", url);

                if (url.startsWith("abook")) {
                    final Uri uri = Uri.parse(url);

                    if (url.contains(ABookKeys.ABOOK_CHECK_API)) {
                        ((ContentViewActivity)context).commonShouldOverrideUrlLoading(uri, currentTaskDto);
                    }

                    return true;
                }

                return false;
            }
        });
    }

    public void addOperationTaskIcon(final ZoomRelativeLayout rootLayout, final OperationTaskDto dto) {
        RelativeLayout.LayoutParams params;
        final float density = mContext.getResources().getDisplayMetrics().density;
        View taskView;
        int width;
        int height;
        if(dto.taskCode == null || dto.taskCode.isEmpty()) {
            // ホットスポットアイコンで表示
            Logger.d(TAG, String.format("[ActionOperationTaskIcon] : taskCode=%s, dto.pdfX:%f, dto.pdfY=%f", dto.taskCode, dto.pdfX, dto.pdfY));
            final ActionOperationTaskIcon taskIcon = new ActionOperationTaskIcon(mContext);
            taskIcon.startBlinkAnimation();
            taskIcon.taskKey = dto.taskKey;

            PointF pointView = rootLayout.convertToViewPoint(dto.pdfX, dto.pdfY);

            width = (int) (ICON_WIDTH * density);
            height = (int) (ICON_HEIGHT * density);

            params = new RelativeLayout.LayoutParams(width, height);
            taskIcon.setTranslationX(pointView.x - (width / 2));
            taskIcon.setTranslationY(pointView.y - (height / 2));
            rootLayout.addView(taskIcon, params);

            taskView = taskIcon;
        } else {
            final PointF pointView = rootLayout.convertToViewPoint(dto.pdfX, dto.pdfY);
            if (mContext.mShowPinFlg) {
                // ピンで表示
                final ActionOperationTaskPin taskPin = new ActionOperationTaskPin(mContext, dto);
                taskPin.taskKey = dto.taskKey;

                // ピンのイメージアイコンのサイズセット
                width = (int) mContext.getResources().getDimensionPixelSize(R.dimen.operation_pin_icon_width);
                height = (int) mContext.getResources().getDimensionPixelSize(R.dimen.operation_pin_icon_height);

                params = new RelativeLayout.LayoutParams(width, height);
                taskPin.setVisibility(View.INVISIBLE);
                rootLayout.addView(taskPin, params);
                // 座標x,yのセット
                taskPin.setTranslationX(pointView.x - (width / 2));
                taskPin.setTranslationY(pointView.y - height);
                if (currentTaskDto != null && currentTaskDto.taskKey.equals(taskPin.taskKey) && mContext.getOpenedProjestTask()) {
                    taskPin.startBlinkAnimation();
                } else {
                    taskPin.stopAnimation();
                }
                taskPin.setVisibility(View.VISIBLE);
                taskView = taskPin;
            } else {
                // 作業コードで表示
                final ActionOperationTaskCode taskCode = new ActionOperationTaskCode(mContext, dto);
                //taskCode.startBlinkAnimation();
                taskCode.taskKey = dto.taskKey;

                final int postWidth = (int) (CODE_WIDTH * density);
                final int postHeight = (int) (CODE_HEIGHT * density);

                params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, postHeight);
                taskCode.setLayoutParams(params);
                taskCode.setVisibility(View.INVISIBLE);
                rootLayout.addView(taskCode, params);

                taskView = taskCode;

                taskCode.post(new Runnable() {
                    @Override
                    public void run() {
                        Logger.d(TAG, String.format("[ActionOperationTaskCode] : taskCode=%s, CODE_WIDTH=%d, fX=%d, fY=%d", dto.taskCode, CODE_WIDTH, (int) pointView.x, (int) pointView.y));
                        int realWidth = taskCode.getWidth(); //height is ready, sometimes realWidth = 0
                        // 座標x,yのセット
                        taskCode.setTranslationX(pointView.x - ((realWidth > 0 ? realWidth : postWidth) / 2));
                        taskCode.setTranslationY(pointView.y - (postHeight / 2));
                        if (currentTaskDto != null && currentTaskDto.taskKey.equals(taskCode.taskKey) && mContext.getOpenedProjestTask()) {
                            taskCode.startBlinkAnimation();
                        } else {
                            taskCode.stopAnimation();
                        }
                        taskCode.setVisibility(View.VISIBLE);
                    }
                });
            }
        }

        // 作業のタップイベント
        taskView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                if (mContext.mMoveTaskFlg && mContext.isReportEdit()) {
                    // 指示者且つ、移動モードの場合
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        ClipData data = ClipData.newPlainText("", "");
                        View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
                        view.startDrag(data, shadowBuilder, view, 0);
                        mContext.setCurrentOperationTask(dto);
                    }
                } else {
                    if (event.getAction() == MotionEvent.ACTION_UP) {
                        if (!mContext.getOpenedProjestTask()) {
                            mContext.showOperationTaskLayout(rootLayout, dto, view.getX());
                        }
                    }
                }
                return true;
            }
        });
    }

    public void addAllOperationTaskIcon(final ZoomRelativeLayout rootLayout, final List<OperationTaskDto> dto) {
        for (OperationTaskDto task : dto) {
            task.isFinished = isTaskFinished(task.taskKey);
            addOperationTaskIcon(rootLayout, task);
        }
    }

    /**
     * 作業キーでステータスを取得
     * @param taskKey
     * @return
     */
    public boolean isTaskFinished(String taskKey) {
        if (mTaskDao.getTaskByTaskKey(taskKey) == null) {
            return false;
        }
        return mTaskDao.getTaskByTaskKey(taskKey).taskStatus == FINISHED_STATUS;
    }

    public void showTaskList(int pageNum, boolean isNormalSize) {
        final String script = String.format(SCRIPT_SHOW_TASK_LIST, pageNum + 1);

        RelativeLayout.LayoutParams params;
        if (isNormalSize) {
            params = createParam(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        } else {
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
            int halfWidth = (int) (displayMetrics.density * OperationTaskLayout.HALF_WIDTH);
            int screenWidth = displayMetrics.widthPixels;
            params = createParam(halfWidth, ViewGroup.LayoutParams.WRAP_CONTENT);
            params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        }

        setLayoutParams(params);

        mContext.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mWebView.loadUrl(script);
            }
        });
    }

    public void showTaskForm(ZoomRelativeLayout layout, int mXWalkOpenType, OperationTaskDto operationTaskDto, boolean isNormalSize, float clickX) {
        if (operationTaskDto.taskKey.equals(TEMP_TASK_KEY)) {
            addOperationTaskIcon(layout, operationTaskDto);
            setTaskFormPosition(clickX, isNormalSize);
        }

        this.currentTaskDto = operationTaskDto;

        final String script;

        script = String.format(SCRIPT_SHOW_TASK_REPORT, operationTaskDto.taskKey.equals(TEMP_TASK_KEY) ? "" : operationTaskDto.taskKey);

        mContext.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mWebView.loadUrl(script);
            }
        });
    }

    public void showOperationTaskLayout() {
        if (getVisibility() != View.VISIBLE) {
            setVisibility(View.VISIBLE);
            mContext.setOperationTaskViewStatus(true);
        }
    }

    public void taskWebViewLoadUrl(String url) {
        mWebView.loadUrl(url);
    }

    private RelativeLayout.LayoutParams createParam(int w, int h) {
        return new RelativeLayout.LayoutParams(w, h);
    }

    public void setTaskFormPosition(float screenX, boolean isNormalSize) {
        RelativeLayout.LayoutParams params;
        if (isNormalSize) {
            params = createParam(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        } else {
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
            int halfWidth = (int) (displayMetrics.density * OperationTaskLayout.HALF_WIDTH);
            int screenWidth = displayMetrics.widthPixels;
            params = createParam(halfWidth, ViewGroup.LayoutParams.WRAP_CONTENT);

            if (screenX < screenWidth / 2) {
                params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
            } else {
                params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
            }
        }

        setLayoutParams(params);
    }

    public void setTaskFormPosition(String taskKey, boolean isNormalSize) {
        RelativeLayout.LayoutParams params;
        if (isNormalSize) {
            params = createParam(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            setLayoutParams(params);
        } else {
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();


            int halfWidth = (int) (displayMetrics.density * OperationTaskLayout.HALF_WIDTH);
            params = createParam(halfWidth, ViewGroup.LayoutParams.WRAP_CONTENT);

            if (!StringUtil.isNullOrEmpty(taskKey)) {
                TaskDto taskDto = mTaskDao.getTaskByTaskKey(taskKey);
                if (taskDto != null) {
                    OperationTaskDto operationTaskDto = new OperationTaskDto();
                    operationTaskDto.taskKey = taskDto.taskKey;
                    operationTaskDto.taskCode = taskDto.taskCode;

                    JSONObject hotSpot = new JSONObject(taskDto.taskHotSpotInfo);
                    operationTaskDto.pdfX = hotSpot.getInt(ABookKeys.PDF_X);
                    operationTaskDto.pdfY = hotSpot.getInt(ABookKeys.PDF_Y);

                    currentTaskDto = operationTaskDto;

                    if (currentLayout.isLeftSideOfPdf((int)operationTaskDto.pdfX)) {
                        params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
                    } else {
                        params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
                    }
                    setLayoutParams(params);
                }
            }
        }
    }

    public int getAlignOfTaskLayer() {
        if (currentTaskDto == null || StringUtil.isNullOrEmpty(currentTaskDto.taskKey)) {
            return RelativeLayout.ALIGN_PARENT_RIGHT;
        }

        if (currentTaskDto.taskKey.equals((TEMP_TASK_KEY))) {
            if (currentLayout.isLeftSideOfPdf((int)currentTaskDto.pdfX)) {
                return RelativeLayout.ALIGN_PARENT_RIGHT;
            } else {
                return RelativeLayout.ALIGN_PARENT_LEFT;
            }
        } else {
            TaskDto taskDto = mTaskDao.getTaskByTaskKey(currentTaskDto.taskKey);
            if (taskDto != null) {
                JSONObject hotSpot = new JSONObject(taskDto.taskHotSpotInfo);
                int pdfX = hotSpot.getInt(ABookKeys.PDF_X);

                if (currentLayout.isLeftSideOfPdf(pdfX)) {
                    return RelativeLayout.ALIGN_PARENT_RIGHT;
                } else {
                    return RelativeLayout.ALIGN_PARENT_LEFT;
                }
            } else {
                return RelativeLayout.ALIGN_PARENT_RIGHT;
            }
        }
    }

    public void setTaskCodeBlinkAnimation() {
        if (currentTaskDto != null && !StringUtil.isNullOrEmpty(currentTaskDto.taskKey)) {

            if (currentTaskDto.taskKey.equals(TEMP_TASK_KEY)) {
                addOperationTaskIcon(currentLayout, currentTaskDto);
            } else {
                if (mContext.getOpenedProjestTask()) {
                    setTaskCodeBlinkAnimation(currentTaskDto.taskKey, true);
                }
            }
        }
    }

    public void setTaskCodeBlinkAnimation(String taskKey, boolean isBlink) {
        for (int i = 0; i < currentLayout.getChildCount(); i++) {
            View v = currentLayout.getChildAt(i);
            if (v instanceof ActionOperationTaskCode) {
                ActionOperationTaskCode code = (ActionOperationTaskCode) v;
                if (code.taskKey.equals(taskKey)) {
                    if (isBlink) {
                        code.startBlinkAnimation();
                    } else {
                        code.stopAnimation();
                    }
                    break;
                }
            } else if (v instanceof ActionOperationTaskPin) {
                ActionOperationTaskPin code = (ActionOperationTaskPin) v;
                if (code.taskKey.equals(taskKey)) {
                    if (isBlink) {
                        code.startBlinkAnimation();
                    } else {
                        code.stopAnimation();
                    }
                    break;
                }
            }
        }
    }

    public void setIconStatus(String taskKey, boolean isDelete) {
        for (int i = 0; i < currentLayout.getChildCount(); i++) {
            View v = currentLayout.getChildAt(i);
            if (v instanceof ActionOperationTaskIcon) {
                ActionOperationTaskIcon icon = (ActionOperationTaskIcon) v;
                if (icon.taskKey.equals(TEMP_TASK_KEY) || icon.taskKey.equals(taskKey)) {
                    icon.stopAnimation();
                    if (isDelete || icon.taskKey.equals(TEMP_TASK_KEY)) {
                        currentLayout.removeView(v);
                    }
                    break;
                }
            } else if (v instanceof ActionOperationTaskCode) {
                ActionOperationTaskCode icon = (ActionOperationTaskCode) v;
                if (icon.taskKey.equals(TEMP_TASK_KEY) || icon.taskKey.equals(taskKey)) {
                    icon.stopAnimation();
                    if (isTaskFinished(taskKey)) {
                        icon.setBackgroundColor(OperationTaskLayout.COLOR_BLUE);
                    } else {
                        icon.setBackgroundColor(OperationTaskLayout.COLOR_ORANGE);
                    }
                    if (isDelete || icon.taskKey.equals(TEMP_TASK_KEY)) {
                        currentLayout.removeView(v);
                    }
                    break;
                }
            } else if (v instanceof ActionOperationTaskPin) {
                ActionOperationTaskPin icon = (ActionOperationTaskPin) v;
                if (icon.taskKey.equals(TEMP_TASK_KEY) || icon.taskKey.equals(taskKey)) {
                    icon.stopAnimation();
                    if (isTaskFinished(taskKey)) {
                        icon.setImageResource(R.drawable.ic_pin_finish);
                    } else {
                        icon.setImageResource(R.drawable.ic_pin_unfinish);
                    }
                    if (isDelete || icon.taskKey.equals(TEMP_TASK_KEY)) {
                        currentLayout.removeView(v);
                    }
                    break;
                }
            }
        }
    }

    public void toggleAllTaskCode(boolean isHide) {
        for (int i = 0; i < currentLayout.getChildCount(); i++) {
            View view = currentLayout.getChildAt(i);
            if (view instanceof ActionOperationTaskCode) {
                if (isHide) {
                    view.setVisibility(View.INVISIBLE);
                } else {
                    view.setVisibility(View.VISIBLE);
                }
            } else if (view instanceof ActionOperationTaskPin) {
                if (isHide) {
                    view.setVisibility(View.INVISIBLE);
                } else {
                    view.setVisibility(View.VISIBLE);
                }
            }
        }
    }

    public static String getTempTaskKey() {
        return TEMP_TASK_KEY;
    }

    private class JsInf {
        @JavascriptInterface
        public void getAttachedDataUrl(String taskKey, String data) {
            ((ABVContentViewActivity) OperationTaskLayout.this.mContext).commonAttachedDataUrl(taskKey, data);
        }
    }
}
