package com.ericsson.uecontrol.core;

import org.apache.log4j.Logger;

import java.io.Serializable;

/**
 * Base class for Ue behaviours that can be used by the executor
 *
 * Created by ezivkoc on 2014-07-15.
 */
public abstract class UeBehaviour implements Serializable{
    private static final Logger log = Logger.getLogger(UeBehaviour.class);
    /** A sleep period for visual queue, mainly for behaviours that instantly finnish **/
    public static final int VISUAL_SLEEP_PERIOD = 200;

    private transient long execTime = -1;
    private transient BehaviourExecutionListener execListener;
    private transient UeControlExecutor executor;


    public synchronized void preRun() {  }

    /**
     * Starts to run the behaviour, this method will block until the execution is done
     */
    public synchronized void run(UeControlExecutor exec){
        execTime = -1;
        this.executor = exec;
        if(execListener != null)
            execListener.executionStarted();
        setProgress(0);

        long startTime = System.currentTimeMillis();
        try {
            execute();
        } catch(Exception e){
            if(execListener != null) execListener.exception(e);
            log.warn(null, e);
        }
        execTime = System.currentTimeMillis() - startTime;

        executor = null;
        if(execListener != null)
            execListener.executionStopped(execTime);
    }

    /**
     * Will stop the currently running behaviour
     */
    public void terminate(){
        executor = null;
    }

    public void reset(){
        execTime = -1;
    }

    /**
     * @return the last measured execution time, -1 if time is not available
     */
    public long getExecTime(){
        return execTime;
    }

    public boolean isRunning(){
        return executor != null;
    }

    /**
     * @return if currently running behaviour should be terminated
     */
    protected boolean stopExecution(){
        return !isRunning();
    }

    protected UeControlExecutor getExecutor(){
        return executor;
    }



    public void setExecutionListener(BehaviourExecutionListener l){
        execListener = l;
    }

    protected void setProgress(float progress){
        if(execListener != null)
            execListener.progressChanged(progress);
    }

    /**
     * Executes the behaviour, will block until behaviour has run to completion.
     */
    protected abstract void execute() throws Exception;

    /**
     * @return the short name of the behaviour
     */
    public abstract String getName();

    /**
     * @return a longer description of the behaviour
     */
    //public abstract String getDescription();

    /**
     * @return a nice String with the current settings
     */
    public abstract String toString();


    public static interface BehaviourExecutionListener {
        public void executionStarted();
        public void progressChanged(float progress);
        public void executionStopped(long executionTime);
        public void exception(Exception e);
    }

}
