package ru.erfolk.jforex.tester;

import com.dukascopy.api.IStrategy;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.Period;
import com.dukascopy.api.system.ISystemListener;
import com.dukascopy.api.system.ITesterClient;
import com.dukascopy.api.system.TesterFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.erfolk.jforex.tester.modules.close.MAOpen;
import ru.erfolk.jforex.utils.CredentialsLoader;
import ru.erfolk.jforex.utils.StrategyContainer;
import singlejartest.Main;

import java.io.File;
import java.text.DateFormat;
import java.util.*;
import java.util.concurrent.Future;

/**
 * Created by IntelliJ IDEA.
 * User: Eugene
 * Date: 23.10.2011
 * Time: 17:31:20
 */
public class Tester implements ISystemListener {
    private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);

    private ITesterClient client;
    private StrategyContainer strategy;
    private Set<Instrument> instruments;

    public Tester(ITesterClient client) {
        this.client = client;
        strategy = new StrategyContainer();
        instruments = new HashSet<Instrument>();
    }

    @Override
    public void onStart(long processId) {
        LOGGER.info("Strategy started: " + processId);
    }

    @Override
    public void onStop(long processId) {
        LOGGER.info("Strategy stopped: " + processId);
        File reportFile = new File("report.html");
        try {
            client.createReport(processId, reportFile);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
        if (client.getStartedStrategies().size() == 0) {
            System.exit(0);
        }
    }

    @Override
    public void onConnect() {
        LOGGER.info("Connected");
    }

    @Override
    public void onDisconnect() {
        LOGGER.info("Disconnected");
    }

    public void setDataInterval(long from, long to) {
        client.setDataInterval(ITesterClient.DataLoadingMethod.ALL_TICKS, from, to);
    }

    public void start() {
        LOGGER.info("Subscribing instruments...");
        client.setSubscribedInstruments(instruments);

        //start the strategy
        LOGGER.info("Starting strategy");
        client.startStrategy(strategy);
        //now it's running
    }

    /**
     * добавляет стратегию к тестированию
     *
     * @param strategy
     */
    public void addStrategy(IStrategy strategy) {
        this.strategy.addStrategy(strategy);
        LOGGER.info("Add strategy " + strategy.getClass());
    }

    /**
     * добавляет к подписке инструмент
     *
     * @param instrument
     */
    public void addInstrument(Instrument instrument) {
        instruments.add(instrument);
        LOGGER.info("Add subscribtion " + instrument);
    }

    public static void main(String[] args) throws Exception {
        //get the instance of the IClient interface
        final ITesterClient client = TesterFactory.getDefaultInstance();

        Tester tester = new Tester(client);

        //set the listener that will receive system events
        client.setSystemListener(tester);

        //connect to the server using jnlp, user name and password
        //connection is needed for data downloading
        if (!CredentialsLoader.connect(client)) {
            LOGGER.error("Failed to connect Dukascopy servers");
            System.exit(1);
        }

        //set instruments that will be used in testing
        MAOpen strategy = new MAOpen(5, 20, Period.FIFTEEN_MINS);
        strategy.addInstrument(Instrument.EURUSD);

        tester.addInstrument(Instrument.EURUSD);
        tester.addStrategy(strategy);

        //setting initial deposit
        client.setInitialDeposit(Instrument.EURUSD.getSecondaryCurrency(), 50000);
        //load data
        LOGGER.info("Downloading data");
        Future<?> future = client.downloadData(null);
        //wait for downloading to complete
        future.get();
        tester.setDataInterval(DateFormat.getDateInstance().parse("01.01.2011").getTime(), System.currentTimeMillis());
        tester.start();
    }


    public static boolean isWeekday(long time) {
        return isWeekday(new Date(time));
    }
    
    public static boolean isWeekday(Date date) {
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        cal.setTime(date);
        int month = cal.get(Calendar.MONTH);
        int hour_limit;
        if (month <= Calendar.FEBRUARY || month >= Calendar.OCTOBER) hour_limit = 22;
        else hour_limit = 21;
        int day = cal.get(Calendar.DAY_OF_WEEK);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        if (day == Calendar.SUNDAY && hour >= hour_limit) return true;
        if (day > Calendar.SUNDAY && day < Calendar.FRIDAY) return true;
        if (day == Calendar.FRIDAY && hour < hour_limit) return true;
        return false;
    }
}
