package jforex.charts;

import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.dukascopy.api.*;
import com.dukascopy.api.drawings.IChannelChartObject;

/**
 * The strategy on its start plots a channel chart object on the chart.
 * If the chart time frame does not match the one from parameters, the
 * channel gets removed from the chart. As soon as the time frame is correct,
 * the channel gets plotted
 *
 */
@RequiresFullAccess  
public class ChannelTimeFrames implements IStrategy {

    private IHistory history;
    private IChart chart;
    private IConsole console;
    
    private ScheduledExecutorService executor;
    
    @Configurable("")
    public Instrument instrument = Instrument.EURUSD;
    @Configurable(value="Execution interval in milliseconds", description="decrease the interval for quicker execution")
    public long execIntervalMillis = 1000;
    @Configurable("Channel period")
    public Period channelShowPeriod = Period.FIVE_MINS;
    
    @Override
    public void onStart(final IContext context) throws JFException {
        history = context.getHistory();
        console = context.getConsole();
        chart = context.getChart(instrument);
        
        if (chart == null){
            console.getErr().println("No chart opened for "+ instrument + " can't plot the chart object!");
            context.stop();
        }
        
        //get from history bars by shift 0 and 5 by chart time frame
        Period period = chart.getSelectedPeriod();
        OfferSide side = chart.getSelectedOfferSide();
        IBar bar0 = history.getBar(instrument, period, side, 0);
        IBar bar5 = history.getBar(instrument, period, side, 5);

        //create and plot the chart object
        IChannelChartObject channel =  chart.getChartObjectFactory().createChannel("channelLine",
            bar5.getTime(), bar5.getClose(), 
            bar0.getTime(), bar0.getClose(),
            bar0.getTime(), bar5.getOpen()
        );    
        chart.addToMainChart(channel);  
        
        //schedule the executor which checks chart time frame
        final ChannelTask hlineTask = new ChannelTask(channel, channelShowPeriod);        
        executor = Executors.newSingleThreadScheduledExecutor();

        Runnable periodicTask = new Runnable() {
            public void run() {
                context.executeTask(hlineTask);
            }
        };

        executor.scheduleAtFixedRate(periodicTask, 0, execIntervalMillis, TimeUnit.MILLISECONDS);
        
    }
    
    private class ChannelTask implements Callable<Object>{
        private final Period channelPeriod;
        private final IChannelChartObject channel;   
        
        public ChannelTask(IChannelChartObject channel, Period channelPeriod) {
            this.channel = channel;
            this.channelPeriod = channelPeriod;
        }
                        
        public Object call() throws Exception {
            //wrong chart period and the channel is on the chart
            if(chart.getSelectedPeriod() != channelPeriod && chart.getAll().contains(channel)){
                chart.remove(channel);
                console.getOut().println("Chart period is not " + channelPeriod + " - remove channel!");
            //correct chart period and the channel is NOT on the chart
            } else if (chart.getSelectedPeriod() == channelPeriod && !chart.getAll().contains(channel)) {
                chart.addToMainChart(channel);
                console.getOut().println("Chart period is " + channelPeriod + " - plot channel!");
            }
            return null;
        }
    }
    
    @Override
    public void onStop() throws JFException {
        //Essential to call shutdown, otherwise the executor service will keep on running
        executor.shutdown();
    }


    @Override
    public void onTick(Instrument instrument, ITick tick) throws JFException {}

    @Override
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {}

    @Override
    public void onMessage(IMessage message) throws JFException {}

    @Override
    public void onAccount(IAccount account) throws JFException {}


}
