package com.atlassian.bitbucket.util;

import org.junit.Test;

import java.util.Arrays;

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

public class VersionTest {

    @Test
    public void testComparisons() {
        Version oneZeroMilestoneOne = new Version("1.0-m1");
        Version oneZeroReleaseCandidateTwo = new Version("1.0.0-rc2");
        Version oneZeroFinal = new Version("1.Final");
        Version oneZeroOneFinal = new Version("1.0.1");
        Version oneOneMilestoneThree = new Version("1.1.0m3");
        Version oneTwoBetaSeven = new Version("1.2.beta7");
        Version oneThreeFinal = new Version("1.3.GA");
        Version oneSevenNine = new Version(1, 7, 9);
        Version oneSevenNineFive = new Version("1.7.9.5");
        Version twoFinal = new Version(2, 0, 0);

        //Assert that milestones, release candidates and final releases of the same version are considered equivalent
        assertEquals(0, oneZeroMilestoneOne.compareTo(oneZeroReleaseCandidateTwo)); //1.0.0-m1 is equivalent to 1.0.0-rc2
        assertEquals(0, oneZeroReleaseCandidateTwo.compareTo(oneZeroFinal)); //1.0.0-rc2 is equivalent to 1.0.0
        assertEquals(0, oneZeroMilestoneOne.compareTo(oneZeroFinal)); //1.0.0-m1 is equivalent to 1.0.0

        //Assert compare is consistent with equals
        assertEquals(oneZeroMilestoneOne, oneZeroReleaseCandidateTwo);
        assertEquals(oneZeroReleaseCandidateTwo, oneZeroFinal);
        assertEquals(oneZeroMilestoneOne, oneZeroFinal);

        //Assert precedence of final releases across major, minor and patch versions
        assertTrue(twoFinal.compareTo(oneThreeFinal) > 0); //2.0.0 is greater than 1.3.0
        assertTrue(oneThreeFinal.compareTo(oneZeroOneFinal) > 0); //1.3.0 is greater than 1.0.1
        assertTrue(oneZeroOneFinal.compareTo(oneZeroFinal) > 0); //1.0.1 is greater than 1.0.0
        assertTrue(oneSevenNineFive.compareTo(oneSevenNine) > 0); //1.7.9.5 is greater than 1.7.9

        //Assert that a milestone or beta of a newer version is considered greater
        assertTrue(oneZeroFinal.compareTo(oneOneMilestoneThree) < 0); //1.0.0 is less than 1.1.0-m3
        assertTrue(oneZeroFinal.compareTo(oneTwoBetaSeven) < 0); //1.0.0 is less than 1.2.0-beta7
        assertTrue(oneOneMilestoneThree.compareTo(oneTwoBetaSeven) < 0); //1.1.0-m3 is less than 1.2.0-beta7
    }

    @Test
    public void testEquals() {
        Version version = new Version("2.0.0");
        assertEquals(version, version); //Because we should
        //noinspection ObjectEqualsNull
        assertFalse(version.equals(null)); //Because we can
        //noinspection EqualsBetweenInconvertibleTypes
        assertFalse(version.equals("2.0.0")); //Ensure no "nice" but non-symmetric fluff is added
        assertFalse(version.equals(new Version("2.0.1")));
    }

    @Test
    public void testGetVersion() {
        Version version = new Version("2.0.0");
        assertEquals(Arrays.asList(2, 0, 0), version.getVersion());

        version = new Version("2.0");
        assertEquals(Arrays.asList(2, 0, 0), version.getVersion());

        version = new Version("2");
        assertEquals(Arrays.asList(2, 0, 0), version.getVersion());
    }

    @Test
    public void testMilestone() {
        Version version = new Version("1.2.3-m1");
        assertVersion("1.2.3", version);
    }

    @Test
    public void testNormalising() {
        Version version = new Version(1); //Should normalise to 3 places
        assertVersion("1.0.0", version); //Should output 3 places

        version = new Version("1.0");
        assertVersion("1.0.0", version);
    }

    @Test
    public void testSnapshot() {
        Version version = new Version("1.1.0-SNAPSHOT"); //Ensure handling of Maven snapshots
        assertVersion("1.1.0", version);
    }

    @Test
    public void testOther() {
        Version version = new Version("1.0.0.beta5"); //Ensure handling of strange beta versions
        assertVersion("1.0.0", version);

        version = new Version("1.7.9.msysgit");
        assertVersion("1.7.9", version);

        version = new Version("2.0.0alpha");
        assertVersion("2.0.0", version);
    }

    private static void assertVersion(String expected, Version actual) {
        assertEquals(expected, actual.toString());
    }
}
