/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed 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 android.graphics.fonts;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.text.TextUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

/**
 * Class that holds information about single font variation axis.
 */
public final class FontVariationAxis {
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private final int mTag;
    private final String mTagString;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private final float mStyleValue;

    /**
     * Construct FontVariationAxis.
     *
     * The axis tag must contain four ASCII characters. Tag string that are longer or shorter than
     * four characters, or contains characters outside of U+0020..U+007E are invalid.
     *
     * @throws IllegalArgumentException If given tag string is invalid.
     */
    public FontVariationAxis(@NonNull String tagString, float styleValue) {
        if (!isValidTag(tagString)) {
            throw new IllegalArgumentException("Illegal tag pattern: " + tagString);
        }
        mTag = makeTag(tagString);
        mTagString = tagString;
        mStyleValue = styleValue;
    }

    /**
     * Returns the OpenType style tag value.
     * @hide
     */
    public int getOpenTypeTagValue() {
        return mTag;
    }

    /**
     * Returns the variable font axis tag associated to this axis.
     */
    public String getTag() {
        return mTagString;
    }

    /**
     * Returns the style value associated to the given axis for this font.
     */
    public float getStyleValue() {
        return mStyleValue;
    }

    /**
     * Returns a valid font variation setting string for this object.
     */
    @Override
    public @NonNull String toString() {
        return "'" + mTagString + "' " + Float.toString(mStyleValue);
    }

    /**
     * The 'tag' attribute value is read as four character values between U+0020 and U+007E
     * inclusive.
     */
    private static final Pattern TAG_PATTERN = Pattern.compile("[\u0020-\u007E]{4}");

    /**
     * Returns true if 'tagString' is valid for font variation axis tag.
     */
    private static boolean isValidTag(String tagString) {
        return tagString != null && TAG_PATTERN.matcher(tagString).matches();
    }

    /**
     * The 'styleValue' attribute has an optional leading '-', followed by '<digits>',
     * '<digits>.<digits>', or '.<digits>' where '<digits>' is one or more of [0-9].
     */
    private static final Pattern STYLE_VALUE_PATTERN =
            Pattern.compile("-?(([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))");

    private static boolean isValidValueFormat(String valueString) {
        return valueString != null && STYLE_VALUE_PATTERN.matcher(valueString).matches();
    }

    /** @hide */
    public static int makeTag(String tagString) {
        final char c1 = tagString.charAt(0);
        final char c2 = tagString.charAt(1);
        final char c3 = tagString.charAt(2);
        final char c4 = tagString.charAt(3);
        return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4;
    }

    /**
     * Construct FontVariationAxis array from font variation settings.
     *
     * The settings string is constructed from multiple pairs of axis tag and style values. The axis
     * tag must contain four ASCII characters and must be wrapped with single quotes (U+0027) or
     * double quotes (U+0022). Axis strings that are longer or shorter than four characters, or
     * contain characters outside of U+0020..U+007E are invalid. If a specified axis name is not
     * defined in the font, the settings will be ignored.
     *
     * <pre>
     *   FontVariationAxis.fromFontVariationSettings("'wdth' 1.0");
     *   FontVariationAxis.fromFontVariationSettings("'AX  ' 1.0, 'FB  ' 2.0");
     * </pre>
     *
     * @param settings font variation settings.
     * @return FontVariationAxis[] the array of parsed font variation axis. {@code null} if settings
     *                             has no font variation settings.
     * @throws IllegalArgumentException If given string is not a valid font variation settings
     *                                  format.
     */
    public static @Nullable FontVariationAxis[] fromFontVariationSettings(
            @Nullable String settings) {
        if (settings == null || settings.isEmpty()) {
            return null;
        }
        final ArrayList<FontVariationAxis> axisList = new ArrayList<>();
        final int length = settings.length();
        for (int i = 0; i < length; i++) {
            final char c = settings.charAt(i);
            if (Character.isWhitespace(c)) {
                continue;
            }
            if (!(c == '\'' || c == '"') || length < i + 6 || settings.charAt(i + 5) != c) {
                throw new IllegalArgumentException(
                        "Tag should be wrapped with double or single quote: " + settings);
            }
            final String tagString = settings.substring(i + 1, i + 5);

            i += 6;  // Move to end of tag.
            int endOfValueString = settings.indexOf(',', i);
            if (endOfValueString == -1) {
                endOfValueString = length;
            }
            final float value;
            try {
                // Float.parseFloat ignores leading/trailing whitespaces.
                value = Float.parseFloat(settings.substring(i, endOfValueString));
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException(
                        "Failed to parse float string: " + e.getMessage());
            }
            axisList.add(new FontVariationAxis(tagString, value));
            i = endOfValueString;
        }
        if (axisList.isEmpty()) {
            return null;
        }
        return axisList.toArray(new FontVariationAxis[0]);
    }

    /**
     * Stringify the array of FontVariationAxis.
     *
     * @param axes an array of FontVariationAxis.
     * @return String a valid font variation settings string.
     */
    public static @NonNull String toFontVariationSettings(@Nullable FontVariationAxis[] axes) {
        if (axes == null) {
            return "";
        }
        return TextUtils.join(",", axes);
    }

    /**
     * Stringify the array of FontVariationAxis.
     * @hide
     */
    public static @NonNull String toFontVariationSettings(@Nullable List<FontVariationAxis> axes) {
        if (axes == null) {
            return "";
        }
        return TextUtils.join(",", axes);
    }

    @Override
    public boolean equals(@Nullable Object o) {
        if (o == this) {
            return true;
        }
        if (o == null || !(o instanceof FontVariationAxis)) {
            return false;
        }
        FontVariationAxis axis = (FontVariationAxis) o;
        return axis.mTag == mTag && axis.mStyleValue == mStyleValue;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mTag, mStyleValue);
    }
}

