package jp.sourceforge.orangesignal.trading;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.util.Date;

import org.apache.commons.lang.SerializationUtils;
import org.junit.Test;

public class DefaultPositionTest {

	@Test
	public void testPosition() {
		new DefaultPosition();
		assertTrue(true);
	}

	@Test
	public void testPositionIntStringPositionTypeStringDateDoubleIntDoubleDouble() {
		new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(true);
	}

	@Test(expected = NullPointerException.class)
	public void testPositionIntStringPositionTypeStringDateDoubleIntDoubleDoubleNullPointerExceptionBySymbol() {
		new DefaultPosition(1, null, PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
	}

	@Test(expected = NullPointerException.class)
	public void testPositionIntStringPositionTypeStringDateDoubleIntDoubleDoubleNullPointerExceptionByPositionType() {
		new DefaultPosition(1, "n225", null, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
	}

	@Test(expected = NullPointerException.class)
	public void testPositionIntStringPositionTypeStringDateDoubleIntDoubleDoubleNullPointerExceptionByEntryDate() {
		new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", null, 10000, 100, 0, 0);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testPositionIntStringPositionTypeStringDateDoubleIntDoubleDoubleIllegalArgumentExceptionByEntryPrice() {
		new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 0, 100, 0, 0);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testPositionIntStringPositionTypeStringDateDoubleIntDoubleDoubleIllegalArgumentExceptionByEntryQuantity() {
		new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 0, 0, 0);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testPositionIntStringPositionTypeStringDateDoubleIntDoubleDoubleIllegalArgumentExceptionByEntryCommission() {
		new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, -1, 0);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testPositionIntStringPositionTypeStringDateDoubleIntDoubleDoubleIllegalArgumentExceptionByEntrySlippage() {
		new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, -1);
	}

	@Test
	public void testClose() {
		final Position position1 = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		final Position splitedPosition1 = position1.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertNull(splitedPosition1);
		assertNull(position1.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 1));

		final DefaultPosition position2 = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		final DefaultPosition splitedPosition2 = position2.close(2, "InactivityStop", new Date(), 9999, 50, 0, 0, 0);
		assertNotNull(splitedPosition2);
		assertEquals(splitedPosition2.entryQuantity, 50);
		assertEquals(position2.entryQuantity, 50);
	}

	@Test(expected = NullPointerException.class)
	public void testCloseNullPointerException() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		position.close(2, "InactivityStop", null, 9999, 100, 0, 0, 0);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testCloseIllegalArgumentExceptionByExitPrice() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		position.close(2, "InactivityStop", new Date(), 0, 100, 0, 0, 0);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testCloseIllegalArgumentExceptionByExitQuantity() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		position.close(2, "InactivityStop", new Date(), 9999, 0, 0, 0, 0);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testCloseIllegalArgumentExceptionByExitCommission() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		position.close(2, "InactivityStop", new Date(), 9999, 100, -1, 0, 0);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testCloseIllegalArgumentExceptionByExitSlippage() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, -1, 0);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testCloseIllegalArgumentExceptionByHold() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, -1);
	}

	@Test
	public void testGetId() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertEquals(position.getId(), 1);
	}

	@Test
	public void testGetSymbol() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertEquals(position.getSymbol(), "n225");
	}

	@Test
	public void testGetType() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertEquals(position.getType(), PositionType.LONG);
	}

	@Test
	public void testGetEntryLabel() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertEquals(position.getEntryLabel(), "MovingAverage2LineCrossLongEntry");
	}

	@Test
	public void testGetEntryDate() {
		final Date now = new Date();
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", now, 10000, 100, 0, 0);
		assertEquals(position.getEntryDate(), now);
	}

	@Test
	public void testGetEntryPrice() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getEntryPrice() == 10000D);
	}

	@Test
	public void testGetEntryQuantity() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertEquals(position.getEntryQuantity(), 100);
	}

	@Test
	public void testGetEntryAmount() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getEntryAmount() == (10000D * 100D));
	}

	@Test
	public void testGetEntryCommission() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getEntryCommission() ==0D);
	}

	@Test
	public void testGetEntrySlippage() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getEntrySlippage() == 0D);
	}

	@Test
	public void testGetExitLabel() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertNull(position.getExitLabel());
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertEquals(position.getExitLabel(), "InactivityStop");
	}

	@Test
	public void testGetExitDate() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertNull(position.getExitDate());
		final Date now = new Date();
		position.close(2, "InactivityStop", now, 9999, 100, 0, 0, 0);
		assertEquals(position.getExitDate(), now);
	}

	@Test
	public void testGetExitPrice() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getExitPrice() == 0D);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position.getExitPrice() == 9999D);
	}

	@Test
	public void testGetExitQuantity() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertEquals(position.getExitQuantity(), 0);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertEquals(position.getExitQuantity(), 100);
	}

	@Test
	public void testGetExitAmount() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getExitAmount() == 0D);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position.getExitAmount() == (9999D * 100D));
	}

	@Test
	public void testGetExitCommission() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getExitCommission() == 0D);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 5, 0, 0);
		assertTrue(position.getExitCommission() == 5D);
	}

	@Test
	public void testGetExitSlippage() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getExitSlippage() == 0D);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 32D, 0);
		assertTrue(position.getExitSlippage() == 32D);
	}

	@Test
	public void testGetHold() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertEquals(position.getHold(), 0);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 10);
		assertEquals(position.getHold(), 10);
	}

	@Test
	public void testIsClosed() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertFalse(position.isClosed());
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position.isClosed());
	}

	@SuppressWarnings("deprecation")
	@Test
	public void testGetDays() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(2009, 6, 10), 10000, 100, 0, 0);
		assertEquals(position.getDays(), 0);
		position.close(2, "InactivityStop", new Date(2009, 6, 12), 9999, 100, 0, 0, 0);
		assertEquals(position.getDays(), 2);
	}

	@Test
	public void testGetGrossSalesDouble() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getGrossSales(5000) == -995000D);
	}

	@Test
	public void testGetNetProfitDoubleDouble() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getNetProfit(10000000D, 5D) == 8999995D);
	}

	@Test
	public void testGetPercent() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getPercent(5000D) == 0.005D);
	}

	@SuppressWarnings("deprecation")
	@Test
	public void testGetDaysDate() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(2009, 6, 10), 10000, 100, 0, 0);
		assertEquals(position.getDays(new Date(2009, 6, 12)), 2);
	}

	@Test
	public void testGetGrossSales() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getGrossSales() == 0D);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position.getGrossSales() == -100D);
	}

	@Test
	public void testGetCommission() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getCommission() == position.getEntryCommission());
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position.getCommission() == (position.getEntryCommission() + position.getExitCommission()));
	}

	@Test
	public void testGetSlippage() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getSlippage() == 0D);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position.getSlippage() == 0D);
	}

	@Test
	public void testGetNetProfit() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getNetProfit() == 0D);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position.getNetProfit() == -100D);
	}

	@Test
	public void testGetGrossProfit() {
		final Position position1 = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position1.getGrossProfit() == 0D);
		position1.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position1.getGrossProfit() == 0D);

		final Position position2 = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position2.getGrossProfit() == 0D);
		position2.close(2, "InactivityStop", new Date(), 10001, 100, 0, 0, 0);
		assertTrue(position2.getGrossProfit() == 100D);
	}

	@Test
	public void testGetGrossLoss() {
		final Position position1 = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position1.getGrossLoss() == 0D);
		position1.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position1.getGrossLoss() == -100D);

		final Position position2 = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position2.getGrossLoss() == 0D);
		position2.close(2, "InactivityStop", new Date(), 10001, 100, 0, 0, 0);
		assertTrue(position2.getGrossLoss() == 0D);
	}

	@Test
	public void testGetPercentCommission() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getPercentCommission() == 0D);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position.getPercentCommission() == (position.getCommission() / position.getEntryAmount()));
	}

	@Test
	public void testGetPercentNetProfit() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getPercentNetProfit() == 0D);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position.getPercentNetProfit() == (position.getNetProfit() / position.getEntryAmount()));
	}

	@Test
	public void testGetPercentGrossProfit() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getPercentGrossProfit() == 0D);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position.getPercentGrossProfit() == (position.getGrossProfit() / position.getEntryAmount()));
	}

	@Test
	public void testGetPercentGrossLoss() {
		final Position position = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(), 10000, 100, 0, 0);
		assertTrue(position.getPercentGrossLoss() == 0D);
		position.close(2, "InactivityStop", new Date(), 9999, 100, 0, 0, 0);
		assertTrue(position.getPercentGrossLoss() == (position.getGrossLoss() / position.getEntryAmount()));
	}

	@SuppressWarnings("deprecation")
	@Test
	public void testCompareTo() {
		final DefaultPosition p1 = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(2009, 1, 1), 10000, 100, 0, 0);
		final DefaultPosition p2 = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(2009, 1, 2), 10000, 100, 0, 0);
		final DefaultPosition p3 = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(2009, 1, 3), 10000, 100, 0, 0);
		final DefaultPosition p4 = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(2009, 1, 1), 10000, 100, 0, 0);
		final DefaultPosition p5 = new DefaultPosition(1, "n225", PositionType.LONG, "MovingAverage2LineCrossLongEntry", new Date(2009, 1, 1), 10000, 100, 0, 0);
		p3.close(2, "InactivityStop", new Date(2009, 1, 6), 10000, 100, 0, 0, 0);
		p4.close(2, "InactivityStop", new Date(2009, 1, 5), 10000, 100, 0, 0, 0);

		assertTrue(p1.compareTo(p2) < 0);
		assertTrue(p1.compareTo(p3) < 0);
		assertTrue(p1.compareTo(p4) < 0);
		assertTrue(p1.compareTo(p5) == 0);

		assertTrue(p2.compareTo(p3) < 0);
		assertTrue(p2.compareTo(p4) < 0);
		assertTrue(p2.compareTo(p5) > 0);

		assertTrue(p3.compareTo(p4) > 0);
		assertTrue(p3.compareTo(p5) > 0);

		assertTrue(p4.compareTo(p5) > 0);
	}

	@Test
	public void testSerialization() {
		final byte[] bytes = SerializationUtils.serialize(new DefaultPosition());
		assertTrue(true);
		final Object obj = SerializationUtils.deserialize(bytes);
		assertTrue(obj instanceof DefaultPosition);
	}

}
