/*
 * Copyright 2017 HugeGraph Authors
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package org.apache.hugegraph.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

public final class VersionUtil {

    /**
     * Compare if a version is inside a range [begin, end)
     * @param version   The version to be compared
     * @param begin     The lower bound of the range
     * @param end       The upper bound of the range
     * @return          true if belong to the range, otherwise false
     */
    public static boolean match(Version version, String begin, String end) {
        E.checkArgumentNotNull(version, "The version to match is null");
        return version.compareTo(new Version(begin)) >= 0 &&
               version.compareTo(new Version(end)) < 0;
    }

    /**
     * Compare if a version is greater than the other one (inclusive)
     * @param version   The version to be compared
     * @param other     The lower bound of the range
     * @return          true if it's greater than the other, otherwise false
     */
    public static boolean gte(String version, String other) {
        E.checkArgumentNotNull(version, "The version to match is null");
        return new Version(version).compareTo(new Version(other)) >= 0;
    }

    /**
     * Check whether a component version is matched expected range,
     * throw an exception if it's not matched.
     * @param version   The version to be checked
     * @param begin     The lower bound of the range
     * @param end       The upper bound of the range
     * @param component The owner component of version
     */
    public static void check(Version version, String begin, String end,
                             String component) {
        E.checkState(VersionUtil.match(version, begin, end),
                     "The version %s of '%s' is not in [%s, %s)",
                     version, component, begin, end);
    }

    /**
     * Get implementation version from manifest in jar
     * @param clazz The class to be load from jar package
     * @return      The implementation version
     */
    public static String getImplementationVersion(Class<?> clazz) {
        /*
         * We don't use Package.getImplementationVersion() due to
         * a duplicate package would override the origin package info.
         * https://stackoverflow.com/questions/1272648/reading-my-own-jars-manifest
         */
        String className = clazz.getSimpleName() + ".class";
        String classPath = clazz.getResource(className).toString();
        if (!classPath.startsWith("jar:file:")) {
          // Class not from JAR
          return null;
        }
        int offset = classPath.lastIndexOf("!");
        assert offset > 0;
        // Get manifest file path
        String manifestPath = classPath.substring(0, offset + 1);
        return getImplementationVersion(manifestPath);
    }

    public static String getImplementationVersion(String manifestPath) {
        manifestPath += "/META-INF/MANIFEST.MF";

        Manifest manifest = null;
        try {
            manifest = new Manifest(new URL(manifestPath).openStream());
        } catch (IOException ignored) {
            return null;
        }
        return manifest.getMainAttributes()
                       .getValue(Attributes.Name.IMPLEMENTATION_VERSION);
    }

    /**
     * Get version from pom.xml
     * @return      The pom version
     */
    public static String getPomVersion() {
        String cmd = "mvn help:evaluate -Dexpression=project.version " +
                     "-q -DforceStdout";
        Process process = null;
        InputStreamReader isr = null;
        try {
            process = Runtime.getRuntime().exec(cmd);
            process.waitFor();

            isr = new InputStreamReader(process.getInputStream());
            BufferedReader br = new BufferedReader(isr);
            return br.readLine();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (isr != null) {
                try {
                    isr.close();
                } catch (Exception ignored) {
                    // pass
                }
            }

            // Destroy child process
            if (process != null) {
                process.destroy();
            }
        }
    }

    /**
     * class Version for compare
     * https://stackoverflow.com/questions/198431/how-do-you-compare-two-version-strings-in-java
     */
    public static class Version implements Comparable<Version> {

        public static Version of(Class<?> clazz) {
            return Version.of(clazz, null);
        }

        public static Version of(Class<?> clazz, String defaultValue) {
            String v = getImplementationVersion(clazz);
            if (v == null) {
                v = defaultValue;
            }
            return v == null ? null : new Version(v);
        }

        public static Version of(String version) {
            return new Version(version);
        }

        /************************** Version define **************************/

        private final String version;
        private final int[] parts;

        public Version(String version) {
            E.checkArgumentNotNull(version, "The version is null");
            E.checkArgument(version.matches("[0-9]+(\\.[0-9]+)*"),
                            "Invalid version format: %s", version);
            this.version = version;
            this.parts = parseVersion(version);
        }

        private static int[] parseVersion(String version) {
            String[] parts = version.split("\\.");
            int[] partsNumber = new int[parts.length];
            for (int i = 0; i < parts.length; i++) {
                partsNumber[i] = Integer.parseInt(parts[i]);
            }
            return partsNumber;
        }

        public final String get() {
            return this.version;
        }

        @Override
        public int compareTo(Version that) {
            if (that == null) {
                return 1;
            }
            int[] thisParts = this.parts;
            int[] thatParts = that.parts;
            int length = Math.max(thisParts.length, thatParts.length);
            for (int i = 0; i < length; i++) {
                int thisPart = i < thisParts.length ? thisParts[i] : 0;
                int thatPart = i < thatParts.length ? thatParts[i] : 0;
                if (thisPart < thatPart) {
                    return -1;
                }
                if (thisPart > thatPart) {
                    return 1;
                }
            }
            return 0;
        }

        @Override
        public boolean equals(Object that) {
            if (this == that) {
                return true;
            }
            if (that == null) {
                return false;
            }
            if (this.getClass() != that.getClass()) {
                return false;
            }
            return this.compareTo((Version) that) == 0;
        }

        @Override
        public int hashCode() {
            int hash = 0;
            for (int i = this.parts.length - 1; i >= 0; i--) {
                int part = this.parts[i];
                if (part == 0 && hash == 0) {
                    continue;
                }
                hash = 31 * hash + Integer.hashCode(part);
            }
            return hash;
        }

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