/*!
Copyright (c) REBUILD <https://getrebuild.com/> and/or its owners. All rights reserved.

rebuild is dual-licensed under commercial and open source licenses (GPLv3).
See LICENSE and COMMERCIAL in the project root for license information.
*/

package com.rebuild.core.service.trigger;

import com.alibaba.fastjson.JSONObject;
import com.rebuild.core.service.general.OperatingContext;

/**
 * 触发动作/操作定义。
 * 注意：如果是异步处理将没有事物，同时会丢失一些线程量（如果需要请手动设置）
 *
 * @author devezhao
 * @since 2019/05/23
 */
public abstract class TriggerAction {

    /**
     * 自己
     */
    public static final String SOURCE_SELF = "$PRIMARY$";
    /**
     * 任意实体（字段匹配）
     */
    public static final String TARGET_ANY = "$";

    final protected ActionContext actionContext;

    protected TriggerAction(ActionContext actionContext) {
        this.actionContext = actionContext;
    }

    public ActionContext getActionContext() {
        return actionContext;
    }

    abstract public ActionType getType();

    abstract public Object execute(OperatingContext operatingContext) throws TriggerException;

    /**
     * v4.1 延迟执行
     *
     * @param originTriggerSource v4.3 原始触发源（才能异步）
     * @return
     */
    protected boolean isAsyncMode(boolean originTriggerSource) {
        if (!originTriggerSource) return false;
        return actionContext != null
                && ((JSONObject) actionContext.getActionContent()).getBooleanValue("asyncMode");
    }

    /**
     * v4.3 主记录更新时同步执行
     *
     * @return
     */
    public boolean isExecOnMainUpdate43() {
        return actionContext != null
                && ((JSONObject) actionContext.getActionContent()).getBooleanValue("execOnMainUpdate");
    }

    /**
     * 如果是删除动作，会先调用此方法。可在此方法中保持一些数据状态，以便删除后还可继续使用
     *
     * @param operatingContext
     * @throws TriggerException
     */
    protected void prepare(OperatingContext operatingContext) throws TriggerException {
    }

    /**
     * 执行后进行清理工作。注意：只有同步任务并且不是用新事物的任务才会触发
     */
    public void clean() {
    }

    /**
     * 实体是否可用此触发器
     *
     * @param entityCode
     * @return
     */
    public boolean isUsableSourceEntity(int entityCode) {
        return true;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()) + "#" + actionContext.getConfigId();
    }
}
