/*
 * Copyright (C) 2015 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.support.app.recommendation;

import android.app.Notification;
import android.os.Bundle;

/**
 * <p>
 * Helper class to add content info extensions to notifications. To create a notification with
 * content info extensions:
 * <ol>
 * <li>Create an {@link Notification.Builder}, setting any desired properties.
 * <li>Create a {@link RecommendationExtender}.
 * <li>Set content info specific properties using the {@code add} and {@code set} methods of
 * {@link RecommendationExtender}.
 * <li>Call {@link android.app.Notification.Builder#extend(Notification.Extender) 
 * Notification.Builder.extend(Notification.Extender)} to apply the extensions to a notification.
 * </ol>
 *
 * <pre class="prettyprint">Notification notification = new Notification.Builder(context) * ... * .extend(new RecommendationExtender() * .set*(...)) * .build(); * </pre>
 * <p>
 * Content info extensions can be accessed on an existing notification by using the
 * {@code RecommendationExtender(Notification)} constructor, and then using the {@code get} methods
 * to access values.
 */
public final class RecommendationExtender implements Notification.Extender {
    private static final String TAG = "RecommendationExtender";

    // Key for the Content info extensions bundle in the main Notification extras bundle
    private static final String EXTRA_CONTENT_INFO_EXTENDER = "android.CONTENT_INFO_EXTENSIONS";

    // Keys within EXTRA_CONTENT_INFO_EXTENDER for individual content info options.

    private static final String KEY_CONTENT_TYPE = "android.contentType";

    private static final String KEY_CONTENT_GENRES = "android.contentGenre";

    private static final String KEY_CONTENT_PRICING_TYPE = "android.contentPricing.type";

    private static final String KEY_CONTENT_PRICING_VALUE = "android.contentPricing.value";

    private static final String KEY_CONTENT_STATUS = "android.contentStatus";

    private static final String KEY_CONTENT_MATURITY_RATING = "android.contentMaturity";

    private static final String KEY_CONTENT_RUN_LENGTH = "android.contentLength";

    private String[] mTypes;
    private String[] mGenres;
    private String mPricingType;
    private String mPricingValue;
    private int mContentStatus = -1;
    private String mMaturityRating;
    private long mRunLength = -1;

    /**
     * Create a {@link RecommendationExtender} with default options.
     */
    public RecommendationExtender() {
    }

    /**
     * Create a {@link RecommendationExtender} from the RecommendationExtender options of an
     * existing Notification.
     *
     * @param notif The notification from which to copy options.
     */
    public RecommendationExtender(Notification notif) {
        Bundle contentBundle = notif.extras == null ?
                null : notif.extras.getBundle(EXTRA_CONTENT_INFO_EXTENDER);
        if (contentBundle != null) {
            mTypes = contentBundle.getStringArray(KEY_CONTENT_TYPE);
            mGenres = contentBundle.getStringArray(KEY_CONTENT_GENRES);
            mPricingType = contentBundle.getString(KEY_CONTENT_PRICING_TYPE);
            mPricingValue = contentBundle.getString(KEY_CONTENT_PRICING_VALUE);
            mContentStatus = contentBundle.getInt(KEY_CONTENT_STATUS, -1);
            mMaturityRating = contentBundle.getString(KEY_CONTENT_MATURITY_RATING);
            mRunLength = contentBundle.getLong(KEY_CONTENT_RUN_LENGTH, -1);
        }
    }

    /**
     * Apply content extensions to a notification that is being built. This is typically called by
     * the {@link android.app.Notification.Builder#extend(Notification.Extender) 
     * Notification.Builder.extend(Notification.Extender)} method of {@link Notification.Builder}.
     */
    @Override
    public Notification.Builder extend(Notification.Builder builder) {
        Bundle contentBundle = new Bundle();

        if (mTypes != null) {
            contentBundle.putStringArray(KEY_CONTENT_TYPE, mTypes);
        }
        if (mGenres != null) {
            contentBundle.putStringArray(KEY_CONTENT_GENRES, mGenres);
        }
        if (mPricingType != null) {
            contentBundle.putString(KEY_CONTENT_PRICING_TYPE, mPricingType);
        }
        if (mPricingValue != null) {
            contentBundle.putString(KEY_CONTENT_PRICING_VALUE, mPricingValue);
        }
        if (mContentStatus != -1) {
            contentBundle.putInt(KEY_CONTENT_STATUS, mContentStatus);
        }
        if (mMaturityRating != null) {
            contentBundle.putString(KEY_CONTENT_MATURITY_RATING, mMaturityRating);
        }
        if (mRunLength > 0) {
            contentBundle.putLong(KEY_CONTENT_RUN_LENGTH, mRunLength);
        }

        builder.getExtras().putBundle(EXTRA_CONTENT_INFO_EXTENDER, contentBundle);
        return builder;
    }

    /**
     * Sets the content types associated with the notification content. The first tag entry will be
     * considered the primary type for the content and will be used for ranking purposes. Other
     * secondary type tags may be provided, if applicable, and may be used for filtering purposes.
     *
     * @param types Array of predefined type tags (see the <code>CONTENT_TYPE_*</code> constants)
     *            that describe the content referred to by a notification.
     */
    public RecommendationExtender setContentTypes(String[] types) {
        mTypes = types;
        return this;
    }

    /**
     * Returns an array containing the content types that describe the content associated with the
     * notification. The first tag entry is considered the primary type for the content, and is used
     * for content ranking purposes.
     *
     * @return An array of predefined type tags (see the <code>CONTENT_TYPE_*</code> constants) that
     *         describe the content associated with the notification.
     * @see RecommendationExtender#setContentTypes
     */
    public String[] getContentTypes() {
        return mTypes;
    }

    /**
     * Returns the primary content type tag for the content associated with the notification.
     *
     * @return A predefined type tag (see the <code>CONTENT_TYPE_*</code> constants) indicating the
     *         primary type for the content associated with the notification.
     * @see RecommendationExtender#setContentTypes
     */
    public String getPrimaryContentType() {
        if (mTypes == null || mTypes.length == 0) {
            return null;
        }
        return mTypes[0];
    }

    /**
     * Sets the content genres associated with the notification content. These genres may be used
     * for content ranking. Genres are open ended String tags.
     * <p>
     * Some examples: "comedy", "action", "dance", "electronica", "racing", etc.
     *
     * @param genres Array of genre string tags that describe the content referred to by a
     *            notification.
     */
    public RecommendationExtender setGenres(String[] genres) {
        mGenres = genres;
        return this;
    }

    /**
     * Returns an array containing the content genres that describe the content associated with the
     * notification.
     *
     * @return An array of genre tags that describe the content associated with the notification.
     * @see RecommendationExtender#setGenres
     */
    public String[] getGenres() {
        return mGenres;
    }

    /**
     * Sets the pricing and availability information for the content associated with the
     * notification. The provided information will indicate the access model for the content (free,
     * rental, purchase or subscription) and the price value (if not free).
     *
     * @param priceType Pricing type for this content. Must be one of the predefined pricing type
     *            tags (see the <code>CONTENT_PRICING_*</code> constants).
     * @param priceValue A string containing a representation of the content price in the current
     *            locale and currency.
     * @return This object for method chaining.
     */
    public RecommendationExtender setPricingInformation(
            @ContentRecommendation.ContentPricing String priceType, String priceValue) {
        mPricingType = priceType;
        mPricingValue = priceValue;
        return this;
    }

    /**
     * Gets the pricing type for the content associated with the notification.
     *
     * @return A predefined tag indicating the pricing type for the content (see the <code> CONTENT_PRICING_*</code>
     *         constants).
     * @see RecommendationExtender#setPricingInformation
     */
    public String getPricingType() {
        return mPricingType;
    }

    /**
     * Gets the price value (when applicable) for the content associated with a notification. The
     * value will be provided as a String containing the price in the appropriate currency for the
     * current locale.
     *
     * @return A string containing a representation of the content price in the current locale and
     *         currency.
     * @see RecommendationExtender#setPricingInformation
     */
    public String getPricingValue() {
        if (mPricingType == null) {
            return null;
        }
        return mPricingValue;
    }

    /**
     * Sets the availability status for the content associated with the notification. This status
     * indicates whether the referred content is ready to be consumed on the device, or if the user
     * must first purchase, rent, subscribe to, or download the content.
     *
     * @param contentStatus The status value for this content. Must be one of the predefined content
     *            status values (see the <code>CONTENT_STATUS_*</code> constants).
     */
    public RecommendationExtender setStatus(
            @ContentRecommendation.ContentStatus int contentStatus) {
        mContentStatus = contentStatus;
        return this;
    }

    /**
     * Returns status value for the content associated with the notification. This status indicates
     * whether the referred content is ready to be consumed on the device, or if the user must first
     * purchase, rent, subscribe to, or download the content.
     *
     * @return The status value for this content, or -1 is a valid status has not been specified
     *         (see the <code>CONTENT_STATUS_*</code> for the defined valid status values).
     * @see RecommendationExtender#setStatus
     */
    public int getStatus() {
        return mContentStatus;
    }

    /**
     * Sets the maturity level rating for the content associated with the notification.
     *
     * @param maturityRating A tag indicating the maturity level rating for the content. This tag
     *            must be one of the predefined maturity rating tags (see the <code> CONTENT_MATURITY_*</code>
     *            constants).
     */
    public RecommendationExtender setMaturityRating(
            @ContentRecommendation.ContentMaturity String maturityRating) {
        mMaturityRating = maturityRating;
        return this;
    }

    /**
     * Returns the maturity level rating for the content associated with the notification.
     *
     * @return returns a predefined tag indicating the maturity level rating for the content (see
     *         the <code>CONTENT_MATURITY_*</code> constants).
     * @see RecommendationExtender#setMaturityRating
     */
    public String getMaturityRating() {
        return mMaturityRating;
    }

    /**
     * Sets the running time (when applicable) for the content associated with the notification.
     *
     * @param length The runing time, in seconds, of the content associated with the notification.
     */
    public RecommendationExtender setRunningTime(long length) {
        if (length < 0) {
            throw new IllegalArgumentException("Invalid value for Running Time");
        }
        mRunLength = length;
        return this;
    }

    /**
     * Returns the running time for the content associated with the notification.
     *
     * @return The running time, in seconds, of the content associated with the notification.
     * @see RecommendationExtender#setRunningTime
     */
    public long getRunningTime() {
        return mRunLength;
    }
}
