/*
 * Copyright (C) 2014 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.speech.tts;

import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

/**
 * Characteristics and features of a Text-To-Speech Voice. Each TTS Engine can expose
 * multiple voices for each locale, with different set of features.
 */
public class Voice implements Parcelable {
    /** Very low, but still intelligible quality of speech synthesis */
    public static final int QUALITY_VERY_LOW = 100;

    /** Low, not human-like quality of speech synthesis */
    public static final int QUALITY_LOW = 200;

    /** Normal quality of speech synthesis */
    public static final int QUALITY_NORMAL = 300;

    /** High, human-like quality of speech synthesis */
    public static final int QUALITY_HIGH = 400;

    /** Very high, almost human-indistinguishable quality of speech synthesis */
    public static final int QUALITY_VERY_HIGH = 500;

    /** Very low expected synthesizer latency (< 20ms) */
    public static final int LATENCY_VERY_LOW = 100;

    /** Low expected synthesizer latency (~20ms) */
    public static final int LATENCY_LOW = 200;

    /** Normal expected synthesizer latency (~50ms) */
    public static final int LATENCY_NORMAL = 300;

    /** Network based expected synthesizer latency (~200ms) */
    public static final int LATENCY_HIGH = 400;

    /** Very slow network based expected synthesizer latency (> 200ms) */
    public static final int LATENCY_VERY_HIGH = 500;

    private final String mName;
    private final Locale mLocale;
    private final int mQuality;
    private final int mLatency;
    private final boolean mRequiresNetworkConnection;
    private final Set<String> mFeatures;

    public Voice(String name,
            Locale locale,
            int quality,
            int latency,
            boolean requiresNetworkConnection,
            Set<String> features) {
        this.mName = name;
        this.mLocale = locale;
        this.mQuality = quality;
        this.mLatency = latency;
        this.mRequiresNetworkConnection = requiresNetworkConnection;
        this.mFeatures = features;
    }

    private Voice(Parcel in) {
        this.mName = in.readString();
        this.mLocale = (Locale)in.readSerializable();
        this.mQuality = in.readInt();
        this.mLatency = in.readInt();
        this.mRequiresNetworkConnection = (in.readByte() == 1);
        this.mFeatures = new HashSet<String>();
        Collections.addAll(this.mFeatures, in.readStringArray());
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mName);
        dest.writeSerializable(mLocale);
        dest.writeInt(mQuality);
        dest.writeInt(mLatency);
        dest.writeByte((byte) (mRequiresNetworkConnection ? 1 : 0));
        dest.writeStringList(new ArrayList<String>(mFeatures));
    }

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

    public static final @android.annotation.NonNull Parcelable.Creator<Voice> CREATOR = new Parcelable.Creator<Voice>() {
        @Override
        public Voice createFromParcel(Parcel in) {
            return new Voice(in);
        }

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


    /**
     * @return The voice's locale
     */
    public Locale getLocale() {
        return mLocale;
    }

    /**
     * @return The voice's quality (higher is better)
     * @see #QUALITY_VERY_HIGH
     * @see #QUALITY_HIGH
     * @see #QUALITY_NORMAL
     * @see #QUALITY_LOW
     * @see #QUALITY_VERY_LOW
     */
    public int getQuality() {
        return mQuality;
    }

    /**
     * @return The voice's latency (lower is better)
     * @see #LATENCY_VERY_LOW
     * @see #LATENCY_LOW
     * @see #LATENCY_NORMAL
     * @see #LATENCY_HIGH
     * @see #LATENCY_VERY_HIGH
     */
    public int getLatency() {
        return mLatency;
    }

    /**
     * @return Does the Voice require a network connection to work.
     */
    public boolean isNetworkConnectionRequired() {
        return mRequiresNetworkConnection;
    }

    /**
     * @return Unique voice name.
     */
    public String getName() {
        return mName;
    }

    /**
     * Returns the set of features it supports for a given voice.
     * Features can either be framework defined, e.g.
     * {@link TextToSpeech.Engine#KEY_FEATURE_NETWORK_TIMEOUT_MS} or engine specific.
     * Engine specific keys must be prefixed by the name of the engine they
     * are intended for. These keys can be used as parameters to
     * {@link TextToSpeech#speak(String, int, java.util.HashMap)} and
     * {@link TextToSpeech#synthesizeToFile(String, java.util.HashMap, String)}.
     *
     * Features values are strings and their values must met restrictions described in their
     * documentation.
     *
     * @return Set instance. May return {@code null} on error.
     */
    public Set<String> getFeatures() {
        return mFeatures;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder(64);
        return builder.append("Voice[Name: ").append(mName)
                .append(", locale: ").append(mLocale)
                .append(", quality: ").append(mQuality)
                .append(", latency: ").append(mLatency)
                .append(", requiresNetwork: ").append(mRequiresNetworkConnection)
                .append(", features: ").append(mFeatures.toString())
                .append("]").toString();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((mFeatures == null) ? 0 : mFeatures.hashCode());
        result = prime * result + mLatency;
        result = prime * result + ((mLocale == null) ? 0 : mLocale.hashCode());
        result = prime * result + ((mName == null) ? 0 : mName.hashCode());
        result = prime * result + mQuality;
        result = prime * result + (mRequiresNetworkConnection ? 1231 : 1237);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        Voice other = (Voice) obj;
        if (mFeatures == null) {
            if (other.mFeatures != null) {
                return false;
            }
        } else if (!mFeatures.equals(other.mFeatures)) {
            return false;
        }
        if (mLatency != other.mLatency) {
            return false;
        }
        if (mLocale == null) {
            if (other.mLocale != null) {
                return false;
            }
        } else if (!mLocale.equals(other.mLocale)) {
            return false;
        }
        if (mName == null) {
            if (other.mName != null) {
                return false;
            }
        } else if (!mName.equals(other.mName)) {
            return false;
        }
        if (mQuality != other.mQuality) {
            return false;
        }
        if (mRequiresNetworkConnection != other.mRequiresNetworkConnection) {
            return false;
        }
        return true;
    }
}
