/*
 * Copyright (C) 2018 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.view.textclassifier;

import android.annotation.FloatRange;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.icu.util.ULocale;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;

import java.util.Locale;
import java.util.Map;

/**
 * Represents the result of language detection of a piece of text.
 * <p>
 * This contains a list of locales, each paired with a confidence score, sorted in decreasing
 * order of those scores. E.g., for a given input text, the model may return
 * {@code [<"en", 0.85>, <"fr", 0.15>]}. This sample result means the model reports that it is
 * 85% likely that the entire text is in English and 15% likely that the entire text is in French,
 * etc. It does not mean that 85% of the input is in English and 15% is in French.
 */
public final class TextLanguage implements Parcelable {

    public static final Creator<TextLanguage> CREATOR = new Creator<TextLanguage>() {
        @Override
        public TextLanguage createFromParcel(Parcel in) {
            return readFromParcel(in);
        }

        @Override
        public TextLanguage[] newArray(int size) {
            return new TextLanguage[size];
        }
    };

    static final TextLanguage EMPTY = new Builder().build();

    @Nullable private final String mId;
    private final EntityConfidence mEntityConfidence;
    private final Bundle mBundle;

    private TextLanguage(
            @Nullable String id,
            EntityConfidence entityConfidence,
            Bundle bundle) {
        mId = id;
        mEntityConfidence = entityConfidence;
        mBundle = bundle;
    }

    /**
     * Returns the id, if one exists, for this object.
     */
    @Nullable
    public String getId() {
        return mId;
    }

    /**
     * Returns the number of possible locales for the processed text.
     */
    @IntRange(from = 0)
    public int getLocaleHypothesisCount() {
        return mEntityConfidence.getEntities().size();
    }

    /**
     * Returns the language locale at the specified index. Locales are ordered from high
     * confidence to low confidence.
     * <p>
     * See {@link #getLocaleHypothesisCount()} for the number of locales available.
     *
     * @throws IndexOutOfBoundsException if the specified index is out of range.
     */
    @NonNull
    public ULocale getLocale(int index) {
        return ULocale.forLanguageTag(mEntityConfidence.getEntities().get(index));
    }

    /**
     * Returns the confidence score for the specified language locale. The value ranges from
     * 0 (low confidence) to 1 (high confidence). 0 indicates that the locale was not found for
     * the processed text.
     */
    @FloatRange(from = 0.0, to = 1.0)
    public float getConfidenceScore(@NonNull ULocale locale) {
        return mEntityConfidence.getConfidenceScore(locale.toLanguageTag());
    }

    /**
     * Returns a bundle containing non-structured extra information about this result. What is
     * returned in the extras is specific to the {@link TextClassifier} implementation.
     *
     * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should prefer
     * to hold a reference to the returned bundle rather than frequently calling this method.
     */
    @NonNull
    public Bundle getExtras() {
        return mBundle.deepCopy();
    }

    @Override
    public String toString() {
        return String.format(
                Locale.US,
                "TextLanguage {id=%s, locales=%s, bundle=%s}",
                mId, mEntityConfidence, mBundle);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mId);
        mEntityConfidence.writeToParcel(dest, flags);
        dest.writeBundle(mBundle);
    }

    private static TextLanguage readFromParcel(Parcel in) {
        return new TextLanguage(
                in.readString(),
                EntityConfidence.CREATOR.createFromParcel(in),
                in.readBundle());
    }

    /**
     * Builder used to build TextLanguage objects.
     */
    public static final class Builder {

        @Nullable private String mId;
        private final Map<String, Float> mEntityConfidenceMap = new ArrayMap<>();
        @Nullable private Bundle mBundle;

        /**
         * Sets a language locale for the processed text and assigns a confidence score. If the
         * locale has already been set, this updates it.
         *
         * @param confidenceScore a value from 0 (low confidence) to 1 (high confidence).
         *      0 implies the locale does not exist for the processed text.
         *      Values greater than 1 are clamped to 1.
         */
        @NonNull
        public Builder putLocale(
                @NonNull ULocale locale,
                @FloatRange(from = 0.0, to = 1.0) float confidenceScore) {
            Preconditions.checkNotNull(locale);
            mEntityConfidenceMap.put(locale.toLanguageTag(), confidenceScore);
            return this;
        }

        /**
         * Sets an optional id for the TextLanguage object.
         */
        @NonNull
        public Builder setId(@Nullable String id) {
            mId = id;
            return this;
        }

        /**
         * Sets a bundle containing non-structured extra information about the TextLanguage object.
         */
        @NonNull
        public Builder setExtras(@NonNull Bundle bundle) {
            mBundle = Preconditions.checkNotNull(bundle);
            return this;
        }

        /**
         * Builds and returns a new TextLanguage object.
         * <p>
         * If necessary, this method will verify fields, clamp them, and make them immutable.
         */
        @NonNull
        public TextLanguage build() {
            mBundle = mBundle == null ? new Bundle() : mBundle.deepCopy();
            return new TextLanguage(
                    mId,
                    new EntityConfidence(mEntityConfidenceMap),
                    mBundle);
        }
    }

    /**
     * A request object for detecting the language of a piece of text.
     */
    public static final class Request implements Parcelable {

        public static final Creator<Request> CREATOR = new Creator<Request>() {
            @Override
            public Request createFromParcel(Parcel in) {
                return readFromParcel(in);
            }

            @Override
            public Request[] newArray(int size) {
                return new Request[size];
            }
        };

        private final CharSequence mText;
        private final Bundle mExtra;
        @Nullable private String mCallingPackageName;

        private Request(CharSequence text, Bundle bundle) {
            mText = text;
            mExtra = bundle;
        }

        /**
         * Returns the text to process.
         */
        @NonNull
        public CharSequence getText() {
            return mText;
        }

        /**
         * Sets the name of the package that is sending this request.
         * Package-private for SystemTextClassifier's use.
         * @hide
         */
        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
        public void setCallingPackageName(@Nullable String callingPackageName) {
            mCallingPackageName = callingPackageName;
        }

        /**
         * Returns the name of the package that sent this request.
         * This returns null if no calling package name is set.
         */
        @Nullable
        public String getCallingPackageName() {
            return mCallingPackageName;
        }

        /**
         * Returns a bundle containing non-structured extra information about this request.
         *
         * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
         * prefer to hold a reference to the returned bundle rather than frequently calling this
         * method.
         */
        @NonNull
        public Bundle getExtras() {
            return mExtra.deepCopy();
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeCharSequence(mText);
            dest.writeString(mCallingPackageName);
            dest.writeBundle(mExtra);
        }

        private static Request readFromParcel(Parcel in) {
            final CharSequence text = in.readCharSequence();
            final String callingPackageName = in.readString();
            final Bundle extra = in.readBundle();

            final Request request = new Request(text, extra);
            request.setCallingPackageName(callingPackageName);
            return request;
        }

        /**
         * A builder for building TextLanguage requests.
         */
        public static final class Builder {

            private final CharSequence mText;
            @Nullable private Bundle mBundle;

            /**
             * Creates a builder to build TextLanguage requests.
             *
             * @param text the text to process.
             */
            public Builder(@NonNull CharSequence text) {
                mText = Preconditions.checkNotNull(text);
            }

            /**
             * Sets a bundle containing non-structured extra information about the request.
             */
            @NonNull
            public Builder setExtras(@NonNull Bundle bundle) {
                mBundle = Preconditions.checkNotNull(bundle);
                return this;
            }

            /**
             * Builds and returns a new TextLanguage request object.
             * <p>
             * If necessary, this method will verify fields, clamp them, and make them immutable.
             */
            @NonNull
            public Request build() {
                mBundle = mBundle == null ? new Bundle() : mBundle.deepCopy();
                return new Request(mText.toString(), mBundle);
            }
        }
    }
}
