class BarBuilder extends AnalyticBase {

	@SuppressWarnings(value = { "unchecked", "rawtypes" })
	@Override
	public Span process(Span span) {
	    //System.out.println(this + " processing span: " + span);
		this.inputSpan = (SpanImpl)span;

		DataSeriesImpl<DataPointImpl> outputSeries = (DataSeriesImpl)getOutputTimeSeries(BarBuilder.OUTPUT_KEY);
		DataSeriesImpl<DataPointImpl> inputSeries = (DataSeriesImpl)getInputTimeSeries(BarBuilder.INPUT_KEY);
		int inputStartIdx = inputSeries.indexOf(inputSpan.getDate(), false);
		int inputLastIdx = inputSeries.indexOf(inputSpan.getNextDate(), false);

		Period inputPeriod = inputSeries.getPeriod();
        Period outputPeriod = outputSeries.getPeriod();

        boolean barCompleted = false;

        if(inputPeriod.equals(outputPeriod)) {
		    for(int i = inputStartIdx;i <= inputLastIdx;i++) {
		        outputSeries.insertData(inputSeries.get(i));
		    }
		    return new SpanImpl(inputSpan);
		}else{
			if(inputPeriod.size() > 1) {
				throw new IllegalStateException(
					"Can't build bars from Type with an Interval that's not 1. Input=" +
						inputPeriod + ", output=" + outputPeriod);
			}

			if(subscription.getTimeFrame(0).getPeriod().equals(new Period(PeriodType.SECOND, 1))) {
			    System.out.println("debug");
			}

			boolean wasAddedDuringInit = false;
			if(currentMergeBar == null) {
			    wasAddedDuringInit = true;
				currentMergeBar = new BarImpl((BarImpl)inputSeries.get(inputStartIdx));
				workingTargetDate = subscription.getTradingWeek().getNextSessionDate(inputSpan.getDate(), outputPeriod);
				currentMergeBar.setDate(workingTargetDate);
				workingSpan = new SpanImpl(subscription.getTimeFrame(0).getPeriod(), inputSpan.getDate(), inputSpan.getNextDate());
				this.workingSpan.setNextDate(workingTargetDate);
				System.out.println("IS INIT: ADDING NEW BAR " + currentMergeBar + "   " + outputSeries.getPeriod() + "  :  span = " + this.workingSpan);
				outputSeries.add(currentMergeBar);
			}else{
				workingSpan.setDate(workingTargetDate);
			}

			for(int i = wasAddedDuringInit ? inputStartIdx + 1 : inputStartIdx;i <= inputLastIdx;i++) {
				BarImpl currentIdxBar = (BarImpl)inputSeries.get(i);
				if(currentIdxBar.getDate().isAfter(workingTargetDate)) {
					workingTargetDate = subscription.getTradingWeek().getNextSessionDate(workingTargetDate, outputPeriod);
					currentMergeBar = new BarImpl(currentIdxBar);
					currentMergeBar.setDate(workingTargetDate);
					this.workingSpan.setNextDate(workingTargetDate);
					System.out.println("IS AFTER: ADDING NEW BAR " + currentMergeBar + "   " + outputSeries.getPeriod() + "  :  span = " + this.workingSpan);
					outputSeries.add(currentMergeBar);
					barCompleted = true;
				}else{
				    currentMergeBar.merge(currentIdxBar, false);
				    if(workingSpan.getPeriod().equals(new Period(PeriodType.SECOND, 1))) {
				        System.out.println("\tNOT IS AFTER: MERGING NEW BAR " + currentMergeBar + "   " + outputSeries.getPeriod() + "  :  span = " + this.workingSpan);
				    }
				}
			}

			//Notify of change
			valueUpdated();
		}

		return barCompleted ? workingSpan : null;
	}

	  BarBuilder(SeriesSubscription s);

}