/*
 * SPDX-License-Identifier: MIT
 */
package org.ta4j.core.indicators.helpers;

import static org.ta4j.core.TestUtils.assertNumEquals;

import java.util.function.Function;

import org.junit.Before;
import org.junit.Test;
import org.ta4j.core.BarSeries;
import org.ta4j.core.BaseBarSeriesBuilder;
import org.ta4j.core.Indicator;
import org.ta4j.core.indicators.AbstractIndicatorTest;
import org.ta4j.core.num.DecimalNum;
import org.ta4j.core.num.Num;
import org.ta4j.core.num.NumFactory;

@SuppressWarnings("deprecation")
public class CombineIndicatorTest extends AbstractIndicatorTest<Indicator<Num>, Num> {

    private CombineIndicator combinePlus;
    private CombineIndicator combineMinus;
    private CombineIndicator combineMultiply;
    private CombineIndicator combineDivide;
    private CombineIndicator combineMax;
    private CombineIndicator combineMin;

    public CombineIndicatorTest(NumFactory numFactory) {
        super(numFactory);
    }

    @Before
    public void setUp() {
        BarSeries series = new BaseBarSeriesBuilder().withNumFactory(numFactory).build();
        var constantIndicator = new ConstantIndicator<>(series, numOf(4));
        var constantIndicatorTwo = new ConstantIndicator<>(series, numOf(2));

        combinePlus = CombineIndicator.plus(constantIndicator, constantIndicatorTwo);
        combineMinus = CombineIndicator.minus(constantIndicator, constantIndicatorTwo);
        combineMultiply = CombineIndicator.multiply(constantIndicator, constantIndicatorTwo);
        combineDivide = CombineIndicator.divide(constantIndicator, constantIndicatorTwo);
        combineMax = CombineIndicator.max(constantIndicator, constantIndicatorTwo);
        combineMin = CombineIndicator.min(constantIndicator, constantIndicatorTwo);
    }

    @Test
    public void testAllDefaultMathCombineFunctions() {
        assertNumEquals(6, combinePlus.getValue(0));
        assertNumEquals(2, combineMinus.getValue(0));
        assertNumEquals(8, combineMultiply.getValue(0));
        assertNumEquals(2, combineDivide.getValue(0));
        assertNumEquals(4, combineMax.getValue(0));
        assertNumEquals(2, combineMin.getValue(0));
    }

    @Test
    public void testDifferenceIndicator() {

        Function<Number, Num> numFunction = DecimalNum::valueOf;

        BarSeries series = new BaseBarSeriesBuilder().build();
        var mockIndicator = new FixedIndicator<>(series, numFunction.apply(-2.0), numFunction.apply(0.00),
                numFunction.apply(1.00), numFunction.apply(2.53), numFunction.apply(5.87), numFunction.apply(6.00),
                numFunction.apply(10.0));
        var constantIndicator = new ConstantIndicator<>(series, numFunction.apply(6));
        CombineIndicator differenceIndicator = CombineIndicator.minus(constantIndicator, mockIndicator);

        assertNumEquals("8", differenceIndicator.getValue(0));
        assertNumEquals("6", differenceIndicator.getValue(1));
        assertNumEquals("5", differenceIndicator.getValue(2));
        assertNumEquals("3.47", differenceIndicator.getValue(3));
        assertNumEquals("0.13", differenceIndicator.getValue(4));
        assertNumEquals("0", differenceIndicator.getValue(5));
        assertNumEquals("-4", differenceIndicator.getValue(6));
    }
}
