/*
 * Copyright (C) 2013 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.accessibility;

import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings.Secure;
import android.text.TextUtils;

import java.util.ArrayList;
import java.util.Locale;

/**
 * Contains methods for accessing and monitoring preferred video captioning state and visual
 * properties.
 * <p>
 * To obtain a handle to the captioning manager, do the following:
 * <p>
 * <code>
 * <pre>CaptioningManager captioningManager =
 *        (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);</pre>
 * </code>
 */
public class CaptioningManager {
    /** Default captioning enabled value. */
    private static final int DEFAULT_ENABLED = 0;

    /** Default style preset as an index into {@link CaptionStyle#PRESETS}. */
    private static final int DEFAULT_PRESET = 0;

    /** Default scaling value for caption fonts. */
    private static final float DEFAULT_FONT_SCALE = 1;

    private final ArrayList<CaptioningChangeListener>
            mListeners = new ArrayList<CaptioningChangeListener>();
    private final Handler mHandler = new Handler();

    private final ContentResolver mContentResolver;

    /**
     * Creates a new captioning manager for the specified context.
     *
     * @hide
     */
    public CaptioningManager(Context context) {
        mContentResolver = context.getContentResolver();
    }

    /**
     * @return the user's preferred captioning enabled state
     */
    public final boolean isEnabled() {
        return Secure.getInt(
                mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_ENABLED, DEFAULT_ENABLED) == 1;
    }

    /**
     * @return the raw locale string for the user's preferred captioning
     *         language
     * @hide
     */
    public final String getRawLocale() {
        return Secure.getString(mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_LOCALE);
    }

    /**
     * @return the locale for the user's preferred captioning language, or null
     *         if not specified
     */
    public final Locale getLocale() {
        final String rawLocale = getRawLocale();
        if (!TextUtils.isEmpty(rawLocale)) {
            final String[] splitLocale = rawLocale.split("_");
            switch (splitLocale.length) {
                case 3:
                    return new Locale(splitLocale[0], splitLocale[1], splitLocale[2]);
                case 2:
                    return new Locale(splitLocale[0], splitLocale[1]);
                case 1:
                    return new Locale(splitLocale[0]);
            }
        }

        return null;
    }

    /**
     * @return the user's preferred font scaling factor for video captions, or 1 if not
     *         specified
     */
    public final float getFontScale() {
        return Secure.getFloat(
                mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE, DEFAULT_FONT_SCALE);
    }

    /**
     * @return the raw preset number, or the first preset if not specified
     * @hide
     */
    public int getRawUserStyle() {
        return Secure.getInt(
                mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_PRESET, DEFAULT_PRESET);
    }

    /**
     * @return the user's preferred visual properties for captions as a
     *         {@link CaptionStyle}, or the default style if not specified
     */
    public CaptionStyle getUserStyle() {
        final int preset = getRawUserStyle();
        if (preset == CaptionStyle.PRESET_CUSTOM) {
            return CaptionStyle.getCustomStyle(mContentResolver);
        }

        return CaptionStyle.PRESETS[preset];
    }

    /**
     * Adds a listener for changes in the user's preferred captioning enabled
     * state and visual properties.
     *
     * @param listener the listener to add
     */
    public void addCaptioningChangeListener(CaptioningChangeListener listener) {
        synchronized (mListeners) {
            if (mListeners.isEmpty()) {
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_ENABLED);
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR);
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR);
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE);
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR);
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE);
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE);
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_LOCALE);
            }

            mListeners.add(listener);
        }
    }

    private void registerObserver(String key) {
        mContentResolver.registerContentObserver(Secure.getUriFor(key), false, mContentObserver);
    }

    /**
     * Removes a listener previously added using
     * {@link #addCaptioningChangeListener}.
     *
     * @param listener the listener to remove
     */
    public void removeCaptioningChangeListener(CaptioningChangeListener listener) {
        synchronized (mListeners) {
            mListeners.remove(listener);

            if (mListeners.isEmpty()) {
                mContentResolver.unregisterContentObserver(mContentObserver);
            }
        }
    }

    private void notifyEnabledChanged() {
        final boolean enabled = isEnabled();
        synchronized (mListeners) {
            for (CaptioningChangeListener listener : mListeners) {
                listener.onEnabledChanged(enabled);
            }
        }
    }

    private void notifyUserStyleChanged() {
        final CaptionStyle userStyle = getUserStyle();
        synchronized (mListeners) {
            for (CaptioningChangeListener listener : mListeners) {
                listener.onUserStyleChanged(userStyle);
            }
        }
    }

    private void notifyLocaleChanged() {
        final Locale locale = getLocale();
        synchronized (mListeners) {
            for (CaptioningChangeListener listener : mListeners) {
                listener.onLocaleChanged(locale);
            }
        }
    }

    private void notifyFontScaleChanged() {
        final float fontScale = getFontScale();
        synchronized (mListeners) {
            for (CaptioningChangeListener listener : mListeners) {
                listener.onFontScaleChanged(fontScale);
            }
        }
    }

    private final ContentObserver mContentObserver = new ContentObserver(mHandler) {
        @Override
        public void onChange(boolean selfChange, Uri uri) {
            final String uriPath = uri.getPath();
            final String name = uriPath.substring(uriPath.lastIndexOf('/') + 1);
            if (Secure.ACCESSIBILITY_CAPTIONING_ENABLED.equals(name)) {
                notifyEnabledChanged();
            } else if (Secure.ACCESSIBILITY_CAPTIONING_LOCALE.equals(name)) {
                notifyLocaleChanged();
            } else if (Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE.equals(name)) {
                notifyFontScaleChanged();
            } else {
                // We only need a single callback when multiple style properties
                // change in rapid succession.
                mHandler.removeCallbacks(mStyleChangedRunnable);
                mHandler.post(mStyleChangedRunnable);
            }
        }
    };

    /**
     * Runnable posted when user style properties change. This is used to
     * prevent unnecessary change notifications when multiple properties change
     * in rapid succession.
     */
    private final Runnable mStyleChangedRunnable = new Runnable() {
        @Override
        public void run() {
            notifyUserStyleChanged();
        }
    };

    /**
     * Specifies visual properties for video captions, including foreground and
     * background colors, edge properties, and typeface.
     */
    public static final class CaptionStyle {
        /** Packed value for a color of 'none' and a cached opacity of 100%. */
        private static final int COLOR_NONE_OPAQUE = 0x000000FF;

        private static final CaptionStyle WHITE_ON_BLACK;
        private static final CaptionStyle BLACK_ON_WHITE;
        private static final CaptionStyle YELLOW_ON_BLACK;
        private static final CaptionStyle YELLOW_ON_BLUE;
        private static final CaptionStyle DEFAULT_CUSTOM;

        /** @hide */
        public static final CaptionStyle[] PRESETS;

        /** @hide */
        public static final int PRESET_CUSTOM = -1;

        /** Edge type value specifying no character edges. */
        public static final int EDGE_TYPE_NONE = 0;

        /** Edge type value specifying uniformly outlined character edges. */
        public static final int EDGE_TYPE_OUTLINE = 1;

        /** Edge type value specifying drop-shadowed character edges. */
        public static final int EDGE_TYPE_DROP_SHADOW = 2;

        /** Edge type value specifying raised bevel character edges. */
        public static final int EDGE_TYPE_RAISED = 3;

        /** Edge type value specifying depressed bevel character edges. */
        public static final int EDGE_TYPE_DEPRESSED = 4;

        /** The preferred foreground color for video captions. */
        public final int foregroundColor;

        /** The preferred background color for video captions. */
        public final int backgroundColor;

        /**
         * The preferred edge type for video captions, one of:
         * <ul>
         * <li>{@link #EDGE_TYPE_NONE}
         * <li>{@link #EDGE_TYPE_OUTLINE}
         * <li>{@link #EDGE_TYPE_DROP_SHADOW}
         * <li>{@link #EDGE_TYPE_RAISED}
         * <li>{@link #EDGE_TYPE_DEPRESSED}
         * </ul>
         */
        public final int edgeType;

        /**
         * The preferred edge color for video captions, if using an edge type
         * other than {@link #EDGE_TYPE_NONE}.
         */
        public final int edgeColor;

        /** The preferred window color for video captions. */
        public final int windowColor;

        /**
         * @hide
         */
        public final String mRawTypeface;

        private Typeface mParsedTypeface;

        private CaptionStyle(int foregroundColor, int backgroundColor, int edgeType, int edgeColor,
                int windowColor, String rawTypeface) {
            this.foregroundColor = foregroundColor;
            this.backgroundColor = backgroundColor;
            this.edgeType = edgeType;
            this.edgeColor = edgeColor;
            this.windowColor = windowColor;

            mRawTypeface = rawTypeface;
        }

        /**
         * @return the preferred {@link Typeface} for video captions, or null if
         *         not specified
         */
        public Typeface getTypeface() {
            if (mParsedTypeface == null && !TextUtils.isEmpty(mRawTypeface)) {
                mParsedTypeface = Typeface.create(mRawTypeface, Typeface.NORMAL);
            }
            return mParsedTypeface;
        }

        /**
         * @hide
         */
        public static CaptionStyle getCustomStyle(ContentResolver cr) {
            final CaptionStyle defStyle = CaptionStyle.DEFAULT_CUSTOM;
            final int foregroundColor = Secure.getInt(
                    cr, Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR, defStyle.foregroundColor);
            final int backgroundColor = Secure.getInt(
                    cr, Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR, defStyle.backgroundColor);
            final int edgeType = Secure.getInt(
                    cr, Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE, defStyle.edgeType);
            final int edgeColor = Secure.getInt(
                    cr, Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR, defStyle.edgeColor);
            final int windowColor = Secure.getInt(
                    cr, Secure.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR, defStyle.windowColor);

            String rawTypeface = Secure.getString(cr, Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE);
            if (rawTypeface == null) {
                rawTypeface = defStyle.mRawTypeface;
            }

            return new CaptionStyle(foregroundColor, backgroundColor, edgeType, edgeColor,
                    windowColor, rawTypeface);
        }

        static {
            WHITE_ON_BLACK = new CaptionStyle(Color.WHITE, Color.BLACK, EDGE_TYPE_NONE,
                    Color.BLACK, COLOR_NONE_OPAQUE, null);
            BLACK_ON_WHITE = new CaptionStyle(Color.BLACK, Color.WHITE, EDGE_TYPE_NONE,
                    Color.BLACK, COLOR_NONE_OPAQUE, null);
            YELLOW_ON_BLACK = new CaptionStyle(Color.YELLOW, Color.BLACK, EDGE_TYPE_NONE,
                    Color.BLACK, COLOR_NONE_OPAQUE, null);
            YELLOW_ON_BLUE = new CaptionStyle(Color.YELLOW, Color.BLUE, EDGE_TYPE_NONE,
                    Color.BLACK, COLOR_NONE_OPAQUE, null);

            PRESETS = new CaptionStyle[] {
                    WHITE_ON_BLACK, BLACK_ON_WHITE, YELLOW_ON_BLACK, YELLOW_ON_BLUE
            };

            DEFAULT_CUSTOM = WHITE_ON_BLACK;
        }
    }

    /**
     * Listener for changes in captioning properties, including enabled state
     * and user style preferences.
     */
    public static abstract class CaptioningChangeListener {
        /**
         * Called when the captioning enabled state changes.
         *
         * @param enabled the user's new preferred captioning enabled state
         */
        public void onEnabledChanged(boolean enabled) {
        }

        /**
         * Called when the captioning user style changes.
         *
         * @param userStyle the user's new preferred style
         * @see CaptioningManager#getUserStyle()
         */
        public void onUserStyleChanged(CaptionStyle userStyle) {
        }

        /**
         * Called when the captioning locale changes.
         *
         * @param locale the preferred captioning locale
         * @see CaptioningManager#getLocale()
         */
        public void onLocaleChanged(Locale locale) {
        }

        /**
         * Called when the captioning font scaling factor changes.
         *
         * @param fontScale the preferred font scaling factor
         * @see CaptioningManager#getFontScale()
         */
        public void onFontScaleChanged(float fontScale) {
        }
    }
}
