package org.ovirt.engine.core.compat;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

/**
 * Version in .Net style: a.b.c.d when a: major version, b: minor version , c: major revision, d: minor revision
 */
public class Version implements Comparable<Version>, Serializable {
    private static final long serialVersionUID = -3938214651005908651L;

    private int major;
    private int minor;
    private int build;
    private int revision;

    public static final Version v2_2 = new Version(2, 2);
    public static final Version v3_0 = new Version(3, 0);
    public static final Version v3_1 = new Version(3, 1);
    public static final Version v3_2 = new Version(3, 2);
    public static final Version v3_3 = new Version(3, 3);
    public static final List<Version> ALL = Arrays.asList(v2_2, v3_0, v3_1, v3_2, v3_3);


    public Version(String value) {
        this();
        setValue(value);
    }

    public Version() {
        major = minor = build = revision = -1;
    }

    public Version(int major, int minor) {
        this.major = major;
        this.minor = minor;
        build = revision = -1;
    }

    public Version(int major2, int minor2, int build2) {
        this.major = major2;
        this.minor = minor2;
        this.build = build2;
        this.revision = -1;
    }

    public Version(int major2, int minor2, int build2, Integer revision2) {
        this.major = major2;
        this.minor = minor2;
        this.build = build2;
        this.revision = revision2;
    }

    public String getValue() {
        String val = "";

        if (this.major > -1)
            val += this.major;
        if (this.minor > -1)
            val += (val != "" ? "." : "") + this.minor;
        if (this.build > -1)
            val += (val != "" ? "." : "") + this.build;
        if (this.revision > -1)
            val += (val != "" ? "." : "") + this.revision;

        return val;
    }

    public void setValue(String value) {
        if (value == null || value.isEmpty() || value.equals("*")) {
            major = minor = build = revision = -1;
        } else {
            String[] partialVersions = value.split("\\.");
            switch (partialVersions.length) {
            case (4):
                revision = Integer.parseInt(partialVersions[3]);
            case (3):
                build = Integer.parseInt(partialVersions[2]);
            case (2):
                minor = Integer.parseInt(partialVersions[1]);
            case (1):
                major = Integer.parseInt(partialVersions[0]);
            }
        }
    }

    public String toString(int i) {
        StringBuilder sb = new StringBuilder();
        switch (i) {
        case (4):
            sb.append(".").append(revision);
        case (3):
            sb.insert(0, build).insert(0, ".");
        case (2):
            sb.insert(0, minor).insert(0, ".");
        case (1):
            sb.insert(0, major);
        }
        return sb.toString();
    }

    @Override
    public String toString() {
        return this.getValue();
    }

    @Override
    public int compareTo(Version other) {
        if (other == null)
            return 5;
        if (this == other)
            return 0;
        int result = major - other.major;
        if (result == 0) {
            result = minor - other.minor;
            if (result == 0) {
                result = build - other.build;
                if (result == 0) {
                    result = revision - other.revision;
                }
            }
        }
        return result;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + major;
        result = prime * result + minor;
        result = prime * result + revision;
        result = prime * result + build;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null || getClass() != obj.getClass())
            return false;

        Version other = (Version) obj;
        if (major == other.major && minor == other.minor && revision == other.revision && build == other.build) {
            return true;
        }
        return false;

    }

    public static boolean OpEquality(Version v1, Version v2) {
        if (v1 == null) {
            return (v2 == null);
        }
        return v1.equals(v2);
    }

    public static boolean OpInequality(Version v1, Version v2) {
        return !OpEquality(v1, v2);
    }

    public int getMajor() {
        return this.major;
    }

    public int getMinor() {
        return this.minor;
    }

    public int getBuild() {
        return this.build;
    }

    public int getRevision() {
        return this.revision;
    }

}

@@ -1573,23 +1573,53 @@
     
-String val = %22%22
+final StringBuilder val = new StringBuilder()
 ;%0A%0A 
@@ -1637,32 +1637,34 @@
 this.major %3E -1)
+ %7B
 %0A            val
@@ -1663,20 +1663,24 @@
      val
- += 
+.append(
 this.maj
@@ -1677,24 +1677,25 @@
 d(this.major
+)
 ;%0A        if
@@ -1696,201 +1696,318 @@
     
-if (this.minor %3E -1)%0A            val += (val != %22%22 ? %22.%22 : %22%22) + this.minor;%0A        if (this.build %3E -1)%0A            val += (val != %22%22 ? %22.%22 : %22%22) + this.build;%0A        if (this.revision
+%7D%0A        appendVersionComponent(val, this.minor);%0A        appendVersionComponent(val, this.build);%0A        appendVersionComponent(val, this.revision);%0A        return val.toString();%0A    %7D%0A%0A    private static void appendVersionComponent(StringBuilder val, int versionNumber) %7B%0A        if (versionNumber
  %3E -1)
+ %7B
 %0A   
@@ -2019,75 +2019,128 @@
     
-val += (val != %22%22 ? %22.%22 : %22%22) + this.revision;%0A%0A        return val;
+if (val.length() != 0) %7B%0A                val.append(%22.%22);%0A            %7D%0A            val.append(versionNumber);%0A        %7D
 %0A   

Version cleanup