/* ====================================================================
   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.poi.openxml4j.opc;

import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Locale;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;

/**
 * An immutable Open Packaging Convention compliant part name.
 *
 * @see <a href="http://www.ietf.org/rfc/rfc3986.txt">http://www.ietf.org/rfc/rfc3986.txt</a>
 */
public final class PackagePartName implements Comparable<PackagePartName> {

    /**
     * Part name stored as an URI.
     */
    private final URI partNameURI;

    /*
     * URI Characters definition (RFC 3986)
     */

    /**
     * Reserved characters for sub delimiters.
     */
    private static final String RFC3986_PCHAR_SUB_DELIMS = "!$&'()*+,;=";

    /**
     * Unreserved character (+ ALPHA & DIGIT).
     */
    private static final String RFC3986_PCHAR_UNRESERVED_SUP = "-._~";

    /**
     * Authorized reserved characters for pChar.
     */
    private static final String RFC3986_PCHAR_AUTHORIZED_SUP = ":@";

    /**
     * Flag to know if this part name is from a relationship part name.
     */
    private final boolean isRelationship;

    /**
     * Constructor. Makes a ValidPartName object from a java.net.URI
     *
     * @param uri
     *            The URI to validate and to transform into ValidPartName.
     * @param checkConformance
     *            Flag to specify if the constructor have to validate the OPC
     *            conformance. Must be always <code>true</code> except for
     *            special URI like '/' which is needed for internal use by
     *            OpenXML4J but is not valid.
     * @throws InvalidFormatException
     *             Throw if the specified part name is not conform to Open
     *             Packaging Convention specifications.
     * @see java.net.URI
     */
    PackagePartName(URI uri, boolean checkConformance)
            throws InvalidFormatException {
        if (checkConformance) {
            throwExceptionIfInvalidPartUri(uri);
        } else {
            if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(uri)) {
                throw new OpenXML4JRuntimeException(
                        "OCP conformance must be check for ALL part name except special cases : ['/']");
            }
        }
        this.partNameURI = uri;
        this.isRelationship = isRelationshipPartURI(this.partNameURI);
    }

    /**
     * Constructor. Makes a ValidPartName object from a String part name.
     *
     * @param partName
     *            Part name to valid and to create.
     * @param checkConformance
     *            Flag to specify if the constructor have to validate the OPC
     *            conformance. Must be always <code>true</code> except for
     *            special URI like '/' which is needed for internal use by
     *            OpenXML4J but is not valid.
     * @throws InvalidFormatException
     *             Throw if the specified part name is not conform to Open
     *             Packaging Convention specifications.
     */
    PackagePartName(String partName, boolean checkConformance)
            throws InvalidFormatException {
        URI partURI;
        try {
            partURI = new URI(partName);
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(
                    "partName argument is not a valid OPC part name !");
        }

        if (checkConformance) {
            throwExceptionIfInvalidPartUri(partURI);
        } else {
            if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(partURI)) {
                throw new OpenXML4JRuntimeException(
                        "OCP conformance must be check for ALL part name except special cases : ['/']");
            }
        }
        this.partNameURI = partURI;
        this.isRelationship = isRelationshipPartURI(this.partNameURI);
    }

    /**
     * Check if the specified part name is a relationship part name.
     *
     * @param partUri
     *            The URI to check.
     * @return <code>true</code> if this part name respect the relationship
     *         part naming convention else <code>false</code>.
     */
    private boolean isRelationshipPartURI(URI partUri) {
        if (partUri == null) {
            throw new IllegalArgumentException("partUri");
        }

        final String uriPath = partUri.getPath();
        return uriPath != null && uriPath.matches(
                "^.*/" + PackagingURIHelper.RELATIONSHIP_PART_SEGMENT_NAME + "/.*\\"
                        + PackagingURIHelper.RELATIONSHIP_PART_EXTENSION_NAME
                        + "$");
    }

    /**
     * Know if this part name is a relationship part name.
     *
     * @return <code>true</code> if this part name respect the relationship
     *         part naming convention else <code>false</code>.
     */
    public boolean isRelationshipPartURI() {
        return this.isRelationship;
    }

    /**
     * Throws an exception (of any kind) if the specified part name does not
     * follow the Open Packaging Convention specifications naming rules.
     *
     * @param partUri
     *            The part name to check.
     * @throws InvalidFormatException
     *             Throws if the part name is invalid.
     */
    private static void throwExceptionIfInvalidPartUri(URI partUri)
            throws InvalidFormatException {
        if (partUri == null) {
            throw new IllegalArgumentException("partUri");
        }
        // Check if the part name URI is empty [M1.1]
        throwExceptionIfEmptyURI(partUri);

        // Check if the part name URI is absolute
        throwExceptionIfAbsoluteUri(partUri);

        // Check if the part name URI starts with a forward slash [M1.4]
        throwExceptionIfPartNameNotStartsWithForwardSlashChar(partUri);

        // Check if the part name URI ends with a forward slash [M1.5]
        throwExceptionIfPartNameEndsWithForwardSlashChar(partUri);

        // Check if the part name does not have empty segments. [M1.3]
        // Check if a segment ends with a dot ('.') character. [M1.9]
        throwExceptionIfPartNameHaveInvalidSegments(partUri);
    }

    /**
     * Throws an exception if the specified URI is empty. [M1.1]
     *
     * @param partURI
     *            Part URI to check.
     * @throws InvalidFormatException
     *             If the specified URI is empty.
     */
    private static void throwExceptionIfEmptyURI(URI partURI)
            throws InvalidFormatException {
        if (partURI == null) {
            throw new IllegalArgumentException("partURI");
        }

        String uriPath = partURI.getPath();
        if (uriPath == null || uriPath.isEmpty()
                || ((uriPath.length() == 1) && (uriPath.charAt(0) == PackagingURIHelper.FORWARD_SLASH_CHAR))) {
            throw new InvalidFormatException(
                    "A part name shall not be empty [M1.1]: "
                            + partURI.getPath());
        }
    }

    /**
     * Throws an exception if the part name has empty segments. [M1.3]
     *
     * Throws an exception if a segment any characters other than pchar
     * characters. [M1.6]
     *
     * Throws an exception if a segment contain percent-encoded forward slash
     * ('/'), or backward slash ('\') characters. [M1.7]
     *
     * Throws an exception if a segment contain percent-encoded unreserved
     * characters. [M1.8]
     *
     * Throws an exception if the specified part name's segments end with a dot
     * ('.') character. [M1.9]
     *
     * Throws an exception if a segment doesn't include at least one non-dot
     * character. [M1.10]
     *
     * @param partUri
     *            The part name to check.
     * @throws InvalidFormatException
     *             if the specified URI contain an empty segments or if one the
     *             segments contained in the part name, ends with a dot ('.')
     *             character.
     */
    private static void throwExceptionIfPartNameHaveInvalidSegments(URI partUri)
            throws InvalidFormatException {
        if (partUri == null) {
            throw new IllegalArgumentException("partUri");
        }

        // Split the URI into several part and analyze each
        String[] segments = partUri.toASCIIString()
            .replaceFirst("^"+PackagingURIHelper.FORWARD_SLASH_CHAR,"")
            .split(PackagingURIHelper.FORWARD_SLASH_STRING);

        if (segments.length < 1) {
            throw new InvalidFormatException(
                "A part name shall not have empty segments [M1.3]: " + partUri.getPath());
        }

        for (final String seg : segments) {
            if (seg == null || seg.isEmpty()) {
                throw new InvalidFormatException(
                    "A part name shall not have empty segments [M1.3]: " + partUri.getPath());
            }

            if (seg.endsWith(".")) {
                throw new InvalidFormatException(
                    "A segment shall not end with a dot ('.') character [M1.9]: " + partUri.getPath());
            }

            if (seg.replaceAll("\\\\.", "").isEmpty()) {
                // Normally will never been invoked with the previous
                // implementation rule [M1.9]
                throw new InvalidFormatException(
                    "A segment shall include at least one non-dot character. [M1.10]: " + partUri.getPath());
            }

            // Check for rule M1.6, M1.7, M1.8
            checkPCharCompliance(seg);
        }
    }

    /**
     * Throws an exception if a segment any characters other than pchar
     * characters. [M1.6]
     *
     * Throws an exception if a segment contain percent-encoded forward slash
     * ('/'), or backward slash ('\') characters. [M1.7]
     *
     * Throws an exception if a segment contain percent-encoded unreserved
     * characters. [M1.8]
     *
     * @param segment
     *            The segment to check
     */
    private static void checkPCharCompliance(String segment)
            throws InvalidFormatException {
        final int length = segment.length();
        for (int i = 0; i < length; ++i) {
            final char c = segment.charAt(i);

            /* Check rule M1.6 */

            if (
                // Check for digit or letter
                isDigitOrLetter(c) ||
                // Check "-", ".", "_", "~"
                RFC3986_PCHAR_UNRESERVED_SUP.indexOf(c) > -1 ||
                // Check ":", "@"
                RFC3986_PCHAR_AUTHORIZED_SUP.indexOf(c) > -1 ||
                // Check "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
                RFC3986_PCHAR_SUB_DELIMS.indexOf(c) > -1
            ) {
                continue;
            }


            if (c != '%') {
                throw new InvalidFormatException(
                    "A segment shall not hold any characters other than pchar characters. [M1.6]");
            }

            // We certainly found an encoded character, check for length
            // now ( '%' HEXDIGIT HEXDIGIT)
            if ((length - i) < 2 || !isHexDigit(segment.charAt(i+1)) || !isHexDigit(segment.charAt(i+2))) {
                throw new InvalidFormatException("The segment " + segment + " contain invalid encoded character !");
            }

            // Decode the encoded character
            final char decodedChar = (char) Integer.parseInt(segment.substring(i + 1, i + 3), 16);
            i += 2;

            /* Check rule M1.7 */
            if (decodedChar == '/' || decodedChar == '\\') {
                throw new InvalidFormatException(
                    "A segment shall not contain percent-encoded forward slash ('/'), or backward slash ('\\') characters. [M1.7]");
            }

            /* Check rule M1.8 */
            if (
                 // Check for unreserved character like define in RFC3986
                isDigitOrLetter(decodedChar) ||
                // Check for unreserved character "-", ".", "_", "~"
                RFC3986_PCHAR_UNRESERVED_SUP.indexOf(decodedChar) > -1
            ) {
                throw new InvalidFormatException(
                    "A segment shall not contain percent-encoded unreserved characters. [M1.8]");
            }
        }
    }

    /**
     * Throws an exception if the specified part name doesn't start with a
     * forward slash character '/'. [M1.4]
     *
     * @param partUri
     *            The part name to check.
     * @throws InvalidFormatException
     *             If the specified part name doesn't start with a forward slash
     *             character '/'.
     */
    private static void throwExceptionIfPartNameNotStartsWithForwardSlashChar(
            URI partUri) throws InvalidFormatException {
        String uriPath = partUri.getPath();
        if (uriPath.length() > 0
                && uriPath.charAt(0) != PackagingURIHelper.FORWARD_SLASH_CHAR) {
            throw new InvalidFormatException(
                    "A part name shall start with a forward slash ('/') character [M1.4]: "
                            + partUri.getPath());
        }
    }

    /**
     * Throws an exception if the specified part name ends with a forward slash
     * character '/'. [M1.5]
     *
     * @param partUri
     *            The part name to check.
     * @throws InvalidFormatException
     *             If the specified part name ends with a forward slash character
     *             '/'.
     */
    private static void throwExceptionIfPartNameEndsWithForwardSlashChar(
            URI partUri) throws InvalidFormatException {
        String uriPath = partUri.getPath();
        if (uriPath.length() > 0
                && uriPath.charAt(uriPath.length() - 1) == PackagingURIHelper.FORWARD_SLASH_CHAR) {
            throw new InvalidFormatException(
                    "A part name shall not have a forward slash as the last character [M1.5]: "
                            + partUri.getPath());
        }
    }

    /**
     * Throws an exception if the specified URI is absolute.
     *
     * @param partUri
     *            The URI to check.
     * @throws InvalidFormatException
     *             Throws if the specified URI is absolute.
     */
    private static void throwExceptionIfAbsoluteUri(URI partUri) throws InvalidFormatException {
        if (partUri.isAbsolute()) {
            throw new InvalidFormatException("Absolute URI forbidden: " + partUri);
        }
    }

    /**
     * Compare two part names following the rule M1.12 :
     *
     * Part name equivalence is determined by comparing part names as
     * case-insensitive ASCII strings. Packages shall not contain equivalent
     * part names and package implementers shall neither create nor recognize
     * packages with equivalent part names. [M1.12]
     */
    @Override
    public int compareTo(PackagePartName other) {
        // compare with natural sort order
        return compare(this, other);
    }


    /**
     * Retrieves the extension of the part name if any. If there is no extension
     * returns an empty String. Example : '/document/content.xml' =&gt; 'xml'
     *
     * @return The extension of the part name.
     */
    public String getExtension() {
        String fragment = this.partNameURI.getPath();
        if (fragment.length() > 0) {
            int i = fragment.lastIndexOf('.');
            if (i > -1) {
                return fragment.substring(i + 1);
            }
        }
        return "";
    }

    /**
     * Get this part name.
     *
     * @return The name of this part name.
     */
    public String getName() {
        return getURI().toASCIIString();
    }

    /**
     * Part name equivalence is determined by comparing part names as
     * case-insensitive ASCII strings. Packages shall not contain equivalent
     * part names and package implementers shall neither create nor recognize
     * packages with equivalent part names. [M1.12]
     */
    @Override
    public boolean equals(Object other) {
        return (other instanceof PackagePartName) &&
            compare(this.getName(), ((PackagePartName)other).getName()) == 0;
    }

    @Override
    public int hashCode() {
        return getName().toLowerCase(Locale.ROOT).hashCode();
    }

    @Override
    public String toString() {
        return getName();
    }

    /* Getters and setters */

    /**
     * Part name property getter.
     *
     * @return This part name URI.
     */
    public URI getURI() {
        return this.partNameURI;
    }


    /**
     * A natural sort order for package part names, consistent with the
     * requirements of {@code java.util.Comparator}, but simply implemented
     * as a static method.
     * <p>
     * For example, this sorts "file10.png" after "file2.png" (comparing the
     * numerical portion), but sorts "File10.png" before "file2.png"
     * (lexigraphical sort)
     *
     * <p>
     * When comparing part names, the rule M1.12 is followed:
     *
     * Part name equivalence is determined by comparing part names as
     * case-insensitive ASCII strings. Packages shall not contain equivalent
     * part names and package implementers shall neither create nor recognize
     * packages with equivalent part names. [M1.12]
     *
     * @param obj1 first {@code PackagePartName} to compare
     * @param obj2 second {@code PackagePartName} to compare
     * @return a negative integer, zero, or a positive integer as the first argument is less than,
     *         equal to, or greater than the second.
     */
    public static int compare(PackagePartName obj1, PackagePartName obj2) {
        return compare (
            obj1 == null ? null : obj1.getName(),
            obj2 == null ? null : obj2.getName()
        );
    }


    /**
     * A natural sort order for strings, consistent with the
     * requirements of {@code java.util.Comparator}, but simply implemented
     * as a static method.
     * <p>
     * For example, this sorts "file10.png" after "file2.png" (comparing the
     * numerical portion), but sorts "File10.png" before "file2.png"
     * (lexigraphical sort)
     *
     * @param str1 first string to compare
     * @param str2 second string to compare
     * @return a negative integer, zero, or a positive integer as the first argument is less than,
     *         equal to, or greater than the second.
     */
    public static int compare(final String str1, final String str2)
    {
        if (str1 == null) {
            // (null) == (null), (null) < (non-null)
            return (str2 == null ? 0 : -1);
        } else if (str2 == null) {
            // (non-null) > (null)
            return 1;
        }

        if (str1.equalsIgnoreCase(str2)) {
            return 0;
        }
        final String name1 = str1.toLowerCase(Locale.ROOT);
        final String name2 = str2.toLowerCase(Locale.ROOT);

        final int len1 = name1.length();
        final int len2 = name2.length();
        for (int idx1 = 0, idx2 = 0; idx1 < len1 && idx2 < len2; /*nil*/) {
            final char c1 = name1.charAt(idx1++);
            final char c2 = name2.charAt(idx2++);

            if (Character.isDigit(c1) && Character.isDigit(c2)) {
                final int beg1 = idx1 - 1;  // undo previous increment
                while (idx1 < len1 && Character.isDigit(name1.charAt(idx1))) {
                    idx1++;
                }

                final int beg2 = idx2 - 1;  // undo previous increment
                while (idx2 < len2 && Character.isDigit(name2.charAt(idx2))) {
                    idx2++;
                }

                // note: BigInteger for extra safety
                final BigInteger b1 = new BigInteger(name1.substring(beg1, idx1));
                final BigInteger b2 = new BigInteger(name2.substring(beg2, idx2));
                final int cmp = b1.compareTo(b2);
                if (cmp != 0) {
                    return cmp;
                }
            }
            else if (c1 != c2) {
                return (c1 - c2);
            }
        }

        return (len1 - len2);
    }

    private static boolean isDigitOrLetter(char c) {
        return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
    }

    private static boolean isHexDigit(char c) {
        return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
    }
}
