package org.cobbzilla.wizard.model;

import lombok.*;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.io.File;
import java.io.FileFilter;
import java.io.Serializable;
import java.util.Comparator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.daemon.ZillaRuntime.empty;
import static org.cobbzilla.wizard.model.BasicConstraintConstants.*;

@Embeddable @EqualsAndHashCode(callSuper=false)
@NoArgsConstructor @AllArgsConstructor
public class SemanticVersion implements Comparable<SemanticVersion>, Serializable {

    public static final String SEMANTIC_VERSION_RE = "(\\d+)\\.(\\d+)\\.(\\d+)";
    public static final String VERSION_REGEXP = "^" + SEMANTIC_VERSION_RE + "$";
    public static final Pattern VERSION_PATTERN = Pattern.compile(VERSION_REGEXP);

    public static final FileFilter DIR_FILTER = new FileFilter() {
        @Override public boolean accept(File pathname) {
            return pathname.isDirectory() && SemanticVersion.isValid(pathname.getName());
        }
    };

    public static final Comparator<SemanticVersion> COMPARE_LATEST_FIRST = new Comparator<SemanticVersion>() {
        @Override public int compare(SemanticVersion o1, SemanticVersion o2) {
            return o2.compareTo(o1);
        }
    };

    public SemanticVersion (String version) {
        if (empty(version)) die("empty version string");
        final Matcher matcher = VERSION_PATTERN.matcher(version);
        if (!matcher.find()) die("Invalid version: " + version);
        setMajor(Integer.parseInt(matcher.group(1)));
        setMinor(Integer.parseInt(matcher.group(2)));
        setPatch(Integer.parseInt(matcher.group(3)));
    }

    @Max(value=SV_VERSION_MAX, message=SV_MAJOR_TOO_LARGE)
    @Min(value=SV_VERSION_MIN, message=SV_MAJOR_TOO_SMALL)
    @Column(name="major_version", length=SV_VERSION_MAXLEN)
    @Getter @Setter private int major = 1;
    public SemanticVersion incrementMajor () { return new SemanticVersion(major+1, 0, 0); }

    @Max(value=SV_VERSION_MAX, message=SV_MINOR_TOO_LARGE)
    @Min(value=SV_VERSION_MIN, message=SV_MINOR_TOO_SMALL)
    @Column(name="minor_version", length=SV_VERSION_MAXLEN)
    @Getter @Setter private int minor = 0;
    public SemanticVersion incrementMinor () { return new SemanticVersion(major, minor+1, 0); }

    @Max(value=SV_VERSION_MAX, message=SV_PATCH_TOO_LARGE)
    @Min(value=SV_VERSION_MIN, message=SV_PATCH_TOO_SMALL)
    @Column(name="patch_version", length=SV_VERSION_MAXLEN)
    @Getter @Setter private int patch = 0;
    public SemanticVersion incrementPatch () { return new SemanticVersion(major, minor, patch+1); }

    public static SemanticVersion incrementPatch(SemanticVersion other) {
        return new SemanticVersion(other.getMajor(), other.getMinor(), other.getPatch()+1);
    }

    public static boolean isValid (String version) { return VERSION_PATTERN.matcher(version).find(); }

    @Override public String toString () { return major + "." + minor + "." + patch; }

    @Override public int compareTo(SemanticVersion other) {
        if (other == null) throw new IllegalArgumentException("compareTo: argument was null");
        int diff;
        diff = major - other.major; if (diff != 0) return diff;
        diff = minor - other.minor; if (diff != 0) return diff;
        diff = patch - other.patch; if (diff != 0) return diff;
        return 0;
    }

}

@@ -46,16 +46,50 @@
 ombok.*;
+%0Aimport lombok.extern.slf4j.Slf4j;
 %0A%0Aimport
@@ -238,29 +238,8 @@
 in;%0A
-import java.io.File;%0A
 impo
@@ -441,71 +441,9 @@
 ime.
-die;%0Aimport static org.cobbzilla.util.daemon.ZillaRuntime.empty
+*
 ;%0Aim
@@ -596,16 +596,23 @@
 structor
+ @Slf4j
 %0Apublic 
@@ -987,102 +987,19 @@
 R = 
-new FileFilter() %7B%0A        @Override public boolean accept(File pathname) %7B%0A            return
+pathname -%3E
  pat
@@ -1065,33 +1065,16 @@
 Name());
-%0A        %7D%0A    %7D;
 %0A%0A    pu
@@ -1141,20 +1141,16 @@
 _FIRST =
- new
  Compara
@@ -1156,144 +1156,621 @@
 ator
-%3CSemanticVersion%3E() %7B%0A  
+.reverseOrder();%0A%0A    /**%0A     * Is v2 newer than v1?%0A     * @param v1 first version%0A     * @param v2 second version%0A
      
+*
  @
-Override public int compare(SemanticVersion o1, SemanticVersion o2) %7B%0A            return o2.compareTo(o1)
+return true if v2 is newer than v1%0A     */%0A    public static boolean isNewerVersion(String v1, String v2) %7B%0A        if (empty(v1) %7C%7C empty(v2)) return false;%0A        v1 = v1.replaceAll(%22%5B%5E.%5C%5Cd%5D+%22, %22%22);%0A        v2 = v2.replaceAll(%22%5B%5E.%5C%5Cd%5D+%22, %22%22);%0A        try %7B%0A            return new SemanticVersion(v1).compareTo(new SemanticVersion(v2)) %3C 0;%0A        %7D catch (Exception e) %7B%0A            log.error(%22isNewer(%22+v1+%22, %22+v2+%22): returning false due to %22+shortError(e));%0A            return false
 ;%0A  
@@ -1782,17 +1782,16 @@
  %7D%0A    %7D
-;
 %0A%0A    pu

add SemanticVersion comparison utility method