//package jforex;

import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;
///import CommonEvaluateData.Symbol;

import com.dukascopy.api.*;

public class VolumeCheck implements IStrategy {
	@SuppressWarnings( "unused"  )
	private IEngine engine;
	private IConsole console;
//	@SuppressWarnings( "unused"  )
	private IHistory history;
	private IContext context;
	@SuppressWarnings( "unused"  )
	private IIndicators indicators;
	//private IUserInterface userInterface;
	private PrintStream out;
	@SuppressWarnings( "unused"  )
	private PrintStream err;
	@SuppressWarnings( "unused"  )
	private IUserInterface gui;
	//
	
	@Configurable( "Volume diff. % max" )
	public double VolumeDiffPercMax = 0.1;
	
	
/*	
	private Symbol symbol[] = {
		new Symbol( Instrument.AUDCAD, true ),
		new Symbol( Instrument.AUDCHF, true ),
		new Symbol( Instrument.AUDJPY, true ),
		new Symbol( Instrument.AUDNZD, true ),
		new Symbol( Instrument.AUDUSD, true ),
		new Symbol( Instrument.CADCHF, true ),
		new Symbol( Instrument.CADJPY, true ),
		new Symbol( Instrument.CHFJPY, true ),
		new Symbol( Instrument.EURAUD, true ),
		new Symbol( Instrument.EURCAD, true ),
		new Symbol( Instrument.EURCHF, true ),
		new Symbol( Instrument.EURGBP, true ),
		new Symbol( Instrument.EURJPY, true ),
		new Symbol( Instrument.EURNZD, true ),
		new Symbol( Instrument.EURUSD, true ),
		new Symbol( Instrument.GBPAUD, true ),
		new Symbol( Instrument.GBPCAD, true ),
		new Symbol( Instrument.GBPCHF, true ),
		new Symbol( Instrument.GBPJPY, true ),
		new Symbol( Instrument.GBPNZD, true ),
		new Symbol( Instrument.GBPUSD, true ),
		new Symbol( Instrument.NZDCAD, true ),
		new Symbol( Instrument.NZDCHF, true ),
		new Symbol( Instrument.NZDJPY, true ),
		new Symbol( Instrument.NZDUSD, true ),
		new Symbol( Instrument.USDCAD, true ),
		new Symbol( Instrument.USDCHF, true ),
		new Symbol( Instrument.USDJPY, true )
		};
*/
	private Symbol symbol[] = {
		new Symbol( Instrument.EURAUD, true ),
		new Symbol( Instrument.EURCAD, true ),
		new Symbol( Instrument.EURGBP, true ),
		new Symbol( Instrument.EURUSD, true ),
		new Symbol( Instrument.GBPJPY, true ),
		new Symbol( Instrument.GBPUSD, true ),
		};
	
	
	static class Utl {
		//
		public static String measure2Str( long ms ) {
			return (ms/1000) + "." + String.format("%03d", ms%1000);
		}
		public static String dateToStr( long tickTime ) {
			return dateToStr(tickTime, "yyyy-MM-dd HH:mm:ss");

		}
		
		public static String dateToStr( long tickTime, String format ) {
			Calendar cal = Calendar.getInstance(new SimpleTimeZone(0, "GMT"));
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			sdf.setCalendar(cal);
			return sdf.format(tickTime);
		}
		
		@SuppressWarnings( "unchecked" )
		public static <T> T unsecureCast( Object o ) {
			return ( T ) o;
		}

	}
	
	class Symbol {
		//
		Symbol( Instrument instrument, boolean enabled ) {
			this.instrument = instrument;
			this.IsEnabled = enabled;
		}
		//
		Instrument instrument;
		boolean IsEnabled = false;
		boolean IsTempDisabled = false;
		int     PipScale;
		//
		int ReadTicksCount = 0;
		//

	}
	
	
	public void onStart( IContext context ) throws JFException {
		this.engine = context.getEngine();
		this.console = context.getConsole();
		this.history = context.getHistory();
		this.context = context;
		this.indicators = context.getIndicators();
		this.out = console.getOut();
		this.err = console.getErr();
		
		
		onStart_InstrumentsSubscribe();
		
		out.println( "STARTING..." );
		
	//	checkVolume( Period.DAILY, 10, VolumeDiffPercMax );
		checkVolume( Period.ONE_HOUR, 101, VolumeDiffPercMax );

	}

	
	
	private void onStart_InstrumentsSubscribe() {
		//
		Set<Instrument> instruments = new HashSet<Instrument>();
		//
		for ( int i = 0; i < symbol.length; i ++ ){
			if ( !symbol[ i ].IsEnabled ) continue;
			//
			instruments.add( symbol[ i ].instrument );
		}
		//
		context.setSubscribedInstruments( instruments );		
	}
		
	public void onStop() throws JFException {
		out.println( "STOPPING..." );
	}

	public void onAccount( IAccount account ) throws JFException {
	}

	public void onMessage( IMessage message ) throws JFException {
	}

	public void onTick( Instrument instrument, ITick tick ) throws JFException {
		//
	}
		
    public void onBar( Instrument instrument, Period period, IBar askBar, IBar bidBar ) throws JFException {
    	//
    }
    
    
	
    
	public void checkVolume( Period period, int timePeriod, double VolumeDiffPercMax ) throws JFException {
		//
//		List<IBar> AskBarsList;
//		List<IBar> BidBarsList;
		//
		Instrument instrument;
		//
		IBar AskBar;
		IBar BidBar;
		//
		long TimeFrom = 0;
		long TimeTo   = 0;
		long Time     = 0;
		//
		List< ITick > TicksList = new ArrayList< ITick >();
		//
		double BarVolume   = 0;
		double TicksVolume = 0;
		double TicksAskVolume = 0;
		double TicksBidVolume = 0;
		double VolumeDiffPerc = 0;
		//
		for ( int iSmb = 0; iSmb < symbol.length; iSmb ++ ) {
			//
			instrument = symbol[ iSmb ].instrument;
			//
			for ( int i = 0; i <= timePeriod; i ++ ) {
				//
				AskBar = history.getBar( instrument, period, OfferSide.ASK, i );
				BidBar = history.getBar( instrument, period, OfferSide.BID, i );
				//
				BarVolume = AskBar.getVolume() + BidBar.getVolume();
				//
				TimeFrom = history.getStartTimeOfCurrentBar( instrument, period ) - period.getInterval() * i;
				TimeTo   = TimeFrom + period.getInterval();
				Time     = history.getTimeOfLastTick( instrument );
				//
				if ( TimeTo > Time ) TimeTo = Time;
				//
				if ( TicksList != null && !TicksList.isEmpty() ) TicksList.clear();
				//
		//		symbol[ iSmb ].readTicks( TimeFrom, TimeTo, false );
				//
			    try {
					TicksList = history.getTicks( instrument, TimeFrom, TimeTo - 1 );
			    }
			    catch ( Exception exc ) {
		        	out.format( "===" );
					out.format( "fillTicksList: " );
		        	out.format( "%s: ", instrument.toString() );
					out.format( "Exception: %s; ", exc.getMessage() );
		        	out.format( "TmFrom %s; ", Utl.dateToStr( TimeFrom ) );
		        	out.format( "TmTo %s; ", Utl.dateToStr( TimeTo ) );
					out.format( "" );
					out.format( "%n" );
			    }
				//
				TicksVolume = 0;
				TicksAskVolume = 0;
				TicksBidVolume = 0;
				//
		    	for ( ITick tick : TicksList ) {
		    		//
		    		TicksVolume += tick.getAskVolume() + tick.getBidVolume();
		    		TicksAskVolume += tick.getAskVolume();
		    		TicksBidVolume += tick.getBidVolume();
		    	}
				//
		    	if ( BarVolume > 0 ) {
			    	VolumeDiffPerc = ( TicksVolume - BarVolume ) / BarVolume * 100;
		    	}
		    	else {
		    		VolumeDiffPerc = 0;
		    	}
		    	//
		    	if ( Math.abs( VolumeDiffPerc ) > VolumeDiffPercMax ) {
		        	out.format( "%s: ", instrument.toString() );
		            out.format( "I: %d; : ", i );
		            out.format( "TmFrom %s; ", Utl.dateToStr( TimeFrom ) );
		            out.format( "TmTo %s; ", Utl.dateToStr( TimeTo ) );
		        	out.format( "BarVol: %1.0f; ", BarVolume );
		        	out.format( "TicksVol: %1.0f; ", TicksVolume );
		        	out.format( "VolDiff%s: %1.2f; ", "%", VolumeDiffPerc );
		            out.format( "TicksCount: %d; : ", TicksList.size() );
		        	out.format( "TicksAVol: %1.0f; ", TicksAskVolume );
		        	out.format( "TicksBVol: %1.0f; ", TicksBidVolume );
		            out.format( "%n" );
		    		
		    	}
			}
		}
		
	}
	
}