/*
 * 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.commons.lang3;

import java.io.Serializable;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * <p>A contiguous range of characters, optionally negated.</p>
 *
 * <p>Instances are immutable.</p>
 *
 * <p>#ThreadSafe#</p>
 * @since 1.0
 */
// TODO: This is no longer public and will be removed later as CharSet is moved
// to depend on Range.
final class CharRange implements Iterable<Character>, Serializable {

    /**
     * Required for serialization support. Lang version 2.0.
     *
     * @see java.io.Serializable
     */
    private static final long serialVersionUID = 8270183163158333422L;

    /** The first character, inclusive, in the range. */
    private final char start;
    /** The last character, inclusive, in the range. */
    private final char end;
    /** True if the range is everything except the characters specified. */
    private final boolean negated;

    /** Cached toString. */
    private transient String iToString;

    /** Empty array. */
    static final CharRange[] EMPTY_ARRAY = {};

    /**
     * <p>Constructs a {@code CharRange} over a set of characters,
     * optionally negating the range.</p>
     *
     * <p>A negated range includes everything except that defined by the
     * start and end characters.</p>
     *
     * <p>If start and end are in the wrong order, they are reversed.
     * Thus {@code a-e} is the same as {@code e-a}.</p>
     *
     * @param start  first character, inclusive, in this range
     * @param end  last character, inclusive, in this range
     * @param negated  true to express everything except the range
     */
    private CharRange(char start, char end, final boolean negated) {
        if (start > end) {
            final char temp = start;
            start = end;
            end = temp;
        }

        this.start = start;
        this.end = end;
        this.negated = negated;
    }

    /**
     * <p>Constructs a {@code CharRange} over a single character.</p>
     *
     * @param ch  only character in this range
     * @return the new CharRange object
     * @since 2.5
     */
    public static CharRange is(final char ch) {
        return new CharRange(ch, ch, false);
    }

    /**
     * <p>Constructs a negated {@code CharRange} over a single character.</p>
     *
     * <p>A negated range includes everything except that defined by the
     * single character.</p>
     *
     * @param ch  only character in this range
     * @return the new CharRange object
     * @since 2.5
     */
    public static CharRange isNot(final char ch) {
        return new CharRange(ch, ch, true);
    }

    /**
     * <p>Constructs a {@code CharRange} over a set of characters.</p>
     *
     * <p>If start and end are in the wrong order, they are reversed.
     * Thus {@code a-e} is the same as {@code e-a}.</p>
     *
     * @param start  first character, inclusive, in this range
     * @param end  last character, inclusive, in this range
     * @return the new CharRange object
     * @since 2.5
     */
    public static CharRange isIn(final char start, final char end) {
        return new CharRange(start, end, false);
    }

    /**
     * <p>Constructs a negated {@code CharRange} over a set of characters.</p>
     *
     * <p>A negated range includes everything except that defined by the
     * start and end characters.</p>
     *
     * <p>If start and end are in the wrong order, they are reversed.
     * Thus {@code a-e} is the same as {@code e-a}.</p>
     *
     * @param start  first character, inclusive, in this range
     * @param end  last character, inclusive, in this range
     * @return the new CharRange object
     * @since 2.5
     */
    public static CharRange isNotIn(final char start, final char end) {
        return new CharRange(start, end, true);
    }

    // Accessors
    /**
     * <p>Gets the start character for this character range.</p>
     *
     * @return the start char (inclusive)
     */
    public char getStart() {
        return this.start;
    }

    /**
     * <p>Gets the end character for this character range.</p>
     *
     * @return the end char (inclusive)
     */
    public char getEnd() {
        return this.end;
    }

    /**
     * <p>Is this {@code CharRange} negated.</p>
     *
     * <p>A negated range includes everything except that defined by the
     * start and end characters.</p>
     *
     * @return {@code true} if negated
     */
    public boolean isNegated() {
        return negated;
    }

    // Contains
    /**
     * <p>Is the character specified contained in this range.</p>
     *
     * @param ch  the character to check
     * @return {@code true} if this range contains the input character
     */
    public boolean contains(final char ch) {
        return (ch >= start && ch <= end) != negated;
    }

    /**
     * <p>Are all the characters of the passed in range contained in
     * this range.</p>
     *
     * @param range  the range to check against
     * @return {@code true} if this range entirely contains the input range
     * @throws IllegalArgumentException if {@code null} input
     */
    public boolean contains(final CharRange range) {
        Validate.notNull(range, "range");
        if (negated) {
            if (range.negated) {
                return start >= range.start && end <= range.end;
            }
            return range.end < start || range.start > end;
        }
        if (range.negated) {
            return start == 0 && end == Character.MAX_VALUE;
        }
        return start <= range.start && end >= range.end;
    }

    // Basics
    /**
     * <p>Compares two CharRange objects, returning true if they represent
     * exactly the same range of characters defined in the same way.</p>
     *
     * @param obj  the object to compare to
     * @return true if equal
     */
    @Override
    public boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof CharRange)) {
            return false;
        }
        final CharRange other = (CharRange) obj;
        return start == other.start && end == other.end && negated == other.negated;
    }

    /**
     * <p>Gets a hashCode compatible with the equals method.</p>
     *
     * @return a suitable hashCode
     */
    @Override
    public int hashCode() {
        return 83 + start + 7 * end + (negated ? 1 : 0);
    }

    /**
     * <p>Gets a string representation of the character range.</p>
     *
     * @return string representation of this range
     */
    @Override
    public String toString() {
        if (iToString == null) {
            final StringBuilder buf = new StringBuilder(4);
            if (isNegated()) {
                buf.append('^');
            }
            buf.append(start);
            if (start != end) {
                buf.append('-');
                buf.append(end);
            }
            iToString = buf.toString();
        }
        return iToString;
    }

    // Expansions
    /**
     * <p>Returns an iterator which can be used to walk through the characters described by this range.</p>
     *
     * <p>#NotThreadSafe# the iterator is not thread-safe</p>
     * @return an iterator to the chars represented by this range
     * @since 2.5
     */
    @Override
    public Iterator<Character> iterator() {
        return new CharacterIterator(this);
    }

    /**
     * Character {@link Iterator}.
     * <p>#NotThreadSafe#</p>
     */
    private static class CharacterIterator implements Iterator<Character> {
        /** The current character */
        private char current;

        private final CharRange range;
        private boolean hasNext;

        /**
         * Constructs a new iterator for the character range.
         *
         * @param r The character range
         */
        private CharacterIterator(final CharRange r) {
            range = r;
            hasNext = true;

            if (range.negated) {
                if (range.start == 0) {
                    if (range.end == Character.MAX_VALUE) {
                        // This range is an empty set
                        hasNext = false;
                    } else {
                        current = (char) (range.end + 1);
                    }
                } else {
                    current = 0;
                }
            } else {
                current = range.start;
            }
        }

        /**
         * Prepares the next character in the range.
         */
        private void prepareNext() {
            if (range.negated) {
                if (current == Character.MAX_VALUE) {
                    hasNext = false;
                } else if (current + 1 == range.start) {
                    if (range.end == Character.MAX_VALUE) {
                        hasNext = false;
                    } else {
                        current = (char) (range.end + 1);
                    }
                } else {
                    current = (char) (current + 1);
                }
            } else if (current < range.end) {
                current = (char) (current + 1);
            } else {
                hasNext = false;
            }
        }

        /**
         * Has the iterator not reached the end character yet?
         *
         * @return {@code true} if the iterator has yet to reach the character date
         */
        @Override
        public boolean hasNext() {
            return hasNext;
        }

        /**
         * Returns the next character in the iteration
         *
         * @return {@code Character} for the next character
         */
        @Override
        public Character next() {
            if (!hasNext) {
                throw new NoSuchElementException();
            }
            final char cur = current;
            prepareNext();
            return Character.valueOf(cur);
        }

        /**
         * Always throws UnsupportedOperationException.
         *
         * @throws UnsupportedOperationException Always thrown.
         * @see java.util.Iterator#remove()
         */
        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }
}
