/*
 * 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.media;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.provider.OpenableColumns;
import android.util.Log;
import android.util.Pair;
import android.util.Range;
import android.util.Rational;
import android.util.Size;

import com.android.internal.annotations.GuardedBy;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Objects;
import java.util.Vector;
import java.util.concurrent.Executor;

/**
 * Media Utilities
 *
 * This class is hidden but public to allow CTS testing and verification
 * of the static methods and classes.
 *
 * @hide
 */
public class Utils {
    private static final String TAG = "Utils";

    /**
     * Sorts distinct (non-intersecting) range array in ascending order.
     * @throws java.lang.IllegalArgumentException if ranges are not distinct
     */
    public static <T extends Comparable<? super T>> void sortDistinctRanges(Range<T>[] ranges) {
        Arrays.sort(ranges, new Comparator<Range<T>>() {
            @Override
            public int compare(Range<T> lhs, Range<T> rhs) {
                if (lhs.getUpper().compareTo(rhs.getLower()) < 0) {
                    return -1;
                } else if (lhs.getLower().compareTo(rhs.getUpper()) > 0) {
                    return 1;
                }
                throw new IllegalArgumentException(
                        "sample rate ranges must be distinct (" + lhs + " and " + rhs + ")");
            }
        });
    }

    /**
     * Returns the intersection of two sets of non-intersecting ranges
     * @param one a sorted set of non-intersecting ranges in ascending order
     * @param another another sorted set of non-intersecting ranges in ascending order
     * @return the intersection of the two sets, sorted in ascending order
     */
    public static <T extends Comparable<? super T>>
            Range<T>[] intersectSortedDistinctRanges(Range<T>[] one, Range<T>[] another) {
        int ix = 0;
        Vector<Range<T>> result = new Vector<Range<T>>();
        for (Range<T> range: another) {
            while (ix < one.length &&
                    one[ix].getUpper().compareTo(range.getLower()) < 0) {
                ++ix;
            }
            while (ix < one.length &&
                    one[ix].getUpper().compareTo(range.getUpper()) < 0) {
                result.add(range.intersect(one[ix]));
                ++ix;
            }
            if (ix == one.length) {
                break;
            }
            if (one[ix].getLower().compareTo(range.getUpper()) <= 0) {
                result.add(range.intersect(one[ix]));
            }
        }
        return result.toArray(new Range[result.size()]);
    }

    /**
     * Returns the index of the range that contains a value in a sorted array of distinct ranges.
     * @param ranges a sorted array of non-intersecting ranges in ascending order
     * @param value the value to search for
     * @return if the value is in one of the ranges, it returns the index of that range.  Otherwise,
     * the return value is {@code (-1-index)} for the {@code index} of the range that is
     * immediately following {@code value}.
     */
    public static <T extends Comparable<? super T>>
            int binarySearchDistinctRanges(Range<T>[] ranges, T value) {
        return Arrays.binarySearch(ranges, Range.create(value, value),
                new Comparator<Range<T>>() {
                    @Override
                    public int compare(Range<T> lhs, Range<T> rhs) {
                        if (lhs.getUpper().compareTo(rhs.getLower()) < 0) {
                            return -1;
                        } else if (lhs.getLower().compareTo(rhs.getUpper()) > 0) {
                            return 1;
                        }
                        return 0;
                    }
                });
    }

    /**
     * Returns greatest common divisor
     */
    static int gcd(int a, int b) {
        if (a == 0 && b == 0) {
            return 1;
        }
        if (b < 0) {
            b = -b;
        }
        if (a < 0) {
            a = -a;
        }
        while (a != 0) {
            int c = b % a;
            b = a;
            a = c;
        }
        return b;
    }

    /** Returns the equivalent factored range {@code newrange}, where for every
     * {@code e}: {@code newrange.contains(e)} implies that {@code range.contains(e * factor)},
     * and {@code !newrange.contains(e)} implies that {@code !range.contains(e * factor)}.
     */
    static Range<Integer>factorRange(Range<Integer> range, int factor) {
        if (factor == 1) {
            return range;
        }
        return Range.create(divUp(range.getLower(), factor), range.getUpper() / factor);
    }

    /** Returns the equivalent factored range {@code newrange}, where for every
     * {@code e}: {@code newrange.contains(e)} implies that {@code range.contains(e * factor)},
     * and {@code !newrange.contains(e)} implies that {@code !range.contains(e * factor)}.
     */
    static Range<Long>factorRange(Range<Long> range, long factor) {
        if (factor == 1) {
            return range;
        }
        return Range.create(divUp(range.getLower(), factor), range.getUpper() / factor);
    }

    private static Rational scaleRatio(Rational ratio, int num, int den) {
        int common = gcd(num, den);
        num /= common;
        den /= common;
        return new Rational(
                (int)(ratio.getNumerator() * (double)num),     // saturate to int
                (int)(ratio.getDenominator() * (double)den));  // saturate to int
    }

    static Range<Rational> scaleRange(Range<Rational> range, int num, int den) {
        if (num == den) {
            return range;
        }
        return Range.create(
                scaleRatio(range.getLower(), num, den),
                scaleRatio(range.getUpper(), num, den));
    }

    static Range<Integer> alignRange(Range<Integer> range, int align) {
        return range.intersect(
                divUp(range.getLower(), align) * align,
                (range.getUpper() / align) * align);
    }

    static int divUp(int num, int den) {
        return (num + den - 1) / den;
    }

    static long divUp(long num, long den) {
        return (num + den - 1) / den;
    }

    /**
     * Returns least common multiple
     */
    private static long lcm(int a, int b) {
        if (a == 0 || b == 0) {
            throw new IllegalArgumentException("lce is not defined for zero arguments");
        }
        return (long)a * b / gcd(a, b);
    }

    static Range<Integer> intRangeFor(double v) {
        return Range.create((int)v, (int)Math.ceil(v));
    }

    static Range<Long> longRangeFor(double v) {
        return Range.create((long)v, (long)Math.ceil(v));
    }

    static Size parseSize(Object o, Size fallback) {
        if (o == null) {
            return fallback;
        }
        try {
            return Size.parseSize((String) o);
        } catch (ClassCastException e) {
        } catch (NumberFormatException e) {
        }
        Log.w(TAG, "could not parse size '" + o + "'");
        return fallback;
    }

    static int parseIntSafely(Object o, int fallback) {
        if (o == null) {
            return fallback;
        }
        try {
            String s = (String)o;
            return Integer.parseInt(s);
        } catch (ClassCastException e) {
        } catch (NumberFormatException e) {
        }
        Log.w(TAG, "could not parse integer '" + o + "'");
        return fallback;
    }

    static Range<Integer> parseIntRange(Object o, Range<Integer> fallback) {
        if (o == null) {
            return fallback;
        }
        try {
            String s = (String)o;
            int ix = s.indexOf('-');
            if (ix >= 0) {
                return Range.create(
                        Integer.parseInt(s.substring(0, ix), 10),
                        Integer.parseInt(s.substring(ix + 1), 10));
            }
            int value = Integer.parseInt(s);
            return Range.create(value, value);
        } catch (ClassCastException e) {
        } catch (NumberFormatException e) {
        } catch (IllegalArgumentException e) {
        }
        Log.w(TAG, "could not parse integer range '" + o + "'");
        return fallback;
    }

    static Range<Long> parseLongRange(Object o, Range<Long> fallback) {
        if (o == null) {
            return fallback;
        }
        try {
            String s = (String)o;
            int ix = s.indexOf('-');
            if (ix >= 0) {
                return Range.create(
                        Long.parseLong(s.substring(0, ix), 10),
                        Long.parseLong(s.substring(ix + 1), 10));
            }
            long value = Long.parseLong(s);
            return Range.create(value, value);
        } catch (ClassCastException e) {
        } catch (NumberFormatException e) {
        } catch (IllegalArgumentException e) {
        }
        Log.w(TAG, "could not parse long range '" + o + "'");
        return fallback;
    }

    static Range<Rational> parseRationalRange(Object o, Range<Rational> fallback) {
        if (o == null) {
            return fallback;
        }
        try {
            String s = (String)o;
            int ix = s.indexOf('-');
            if (ix >= 0) {
                return Range.create(
                        Rational.parseRational(s.substring(0, ix)),
                        Rational.parseRational(s.substring(ix + 1)));
            }
            Rational value = Rational.parseRational(s);
            return Range.create(value, value);
        } catch (ClassCastException e) {
        } catch (NumberFormatException e) {
        } catch (IllegalArgumentException e) {
        }
        Log.w(TAG, "could not parse rational range '" + o + "'");
        return fallback;
    }

    static Pair<Size, Size> parseSizeRange(Object o) {
        if (o == null) {
            return null;
        }
        try {
            String s = (String)o;
            int ix = s.indexOf('-');
            if (ix >= 0) {
                return Pair.create(
                        Size.parseSize(s.substring(0, ix)),
                        Size.parseSize(s.substring(ix + 1)));
            }
            Size value = Size.parseSize(s);
            return Pair.create(value, value);
        } catch (ClassCastException e) {
        } catch (NumberFormatException e) {
        } catch (IllegalArgumentException e) {
        }
        Log.w(TAG, "could not parse size range '" + o + "'");
        return null;
    }

    /**
     * Creates a unique file in the specified external storage with the desired name. If the name is
     * taken, the new file's name will have '(%d)' to avoid overwriting files.
     *
     * @param context {@link Context} to query the file name from.
     * @param subdirectory One of the directories specified in {@link android.os.Environment}
     * @param fileName desired name for the file.
     * @param mimeType MIME type of the file to create.
     * @return the File object in the storage, or null if an error occurs.
     */
    public static File getUniqueExternalFile(Context context, String subdirectory, String fileName,
            String mimeType) {
        File externalStorage = Environment.getExternalStoragePublicDirectory(subdirectory);
        // Make sure the storage subdirectory exists
        externalStorage.mkdirs();

        File outFile = null;
        try {
            // Ensure the file has a unique name, as to not override any existing file
            outFile = FileUtils.buildUniqueFile(externalStorage, mimeType, fileName);
        } catch (FileNotFoundException e) {
            // This might also be reached if the number of repeated files gets too high
            Log.e(TAG, "Unable to get a unique file name: " + e);
            return null;
        }
        return outFile;
    }

    /**
     * Returns a file's display name from its {@link android.content.ContentResolver.SCHEME_FILE}
     * or {@link android.content.ContentResolver.SCHEME_CONTENT} Uri. The display name of a file
     * includes its extension.
     *
     * @param context Context trying to resolve the file's display name.
     * @param uri Uri of the file.
     * @return the file's display name, or the uri's string if something fails or the uri isn't in
     *            the schemes specified above.
     */
    static String getFileDisplayNameFromUri(Context context, Uri uri) {
        String scheme = uri.getScheme();

        if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            return uri.getLastPathSegment();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            // We need to query the ContentResolver to get the actual file name as the Uri masks it.
            // This means we want the name used for display purposes only.
            String[] proj = {
                    OpenableColumns.DISPLAY_NAME
            };
            try (Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null)) {
                if (cursor != null && cursor.getCount() != 0) {
                    cursor.moveToFirst();
                    return cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                }
            }
        }

        // This will only happen if the Uri isn't either SCHEME_CONTENT or SCHEME_FILE, so we assume
        // it already represents the file's name.
        return uri.toString();
    }

    /**
     * {@code ListenerList} is a helper class that delivers events to listeners.
     *
     * It is written to isolate the <strong>mechanics</strong> of event delivery from the
     * <strong>details</strong> of those events.
     *
     * The {@code ListenerList} is parameterized on the generic type {@code V}
     * of the object delivered by {@code notify()}.
     * This gives compile time type safety over run-time casting of a general {@code Object},
     * much like {@code HashMap&lt;String, Object&gt;} does not give type safety of the
     * stored {@code Object} value and may allow
     * permissive storage of {@code Object}s that are not expected by users of the
     * {@code HashMap}, later resulting in run-time cast exceptions that
     * could have been caught by replacing
     * {@code Object} with a more precise type to enforce a compile time contract.
     *
     * The {@code ListenerList} is implemented as a single method callback
     * - or a "listener" according to Android style guidelines.
     *
     * The {@code ListenerList} can be trivially extended by a suitable lambda to implement
     * a <strong> multiple method abstract class</strong> "callback",
     * in which the generic type {@code V} could be an {@code Object}
     * to encapsulate the details of the parameters of each callback method, and
     * {@code instanceof} could be used to disambiguate which callback method to use.
     * A {@link Bundle} could alternatively encapsulate those generic parameters,
     * perhaps more conveniently.
     * Again, this is a detail of the event, not the mechanics of the event delivery,
     * which this class is concerned with.
     *
     * For details on how to use this class to implement a <strong>single listener</strong>
     * {@code ListenerList}, see notes on {@link #add}.
     *
     * For details on how to optimize this class to implement
     * a listener based on {@link Handler}s
     * instead of {@link Executor}s, see{@link #ListenerList(boolean, boolean, boolean)}.
     *
     * This is a TestApi for CTS Unit Testing, not exposed for general Application use.
     * @hide
     *
     * @param <V> The class of the object returned to the listener.
     */
    @TestApi
    public static class ListenerList<V> {
        /**
         * The Listener interface for callback.
         *
         * @param <V> The class of the object returned to the listener
         */
        public interface Listener<V> {
            /**
             * General event listener interface which is managed by the {@code ListenerList}.
             *
             * @param eventCode is an integer representing the event type. This is an
             *     implementation defined parameter.
             * @param info is the object returned to the listener.  It is expected
             *     that the listener makes a private copy of the {@code info} object before
             *     modification, as it is the same instance passed to all listeners.
             *     This is an implementation defined parameter that may be null.
             */
            void onEvent(int eventCode, @Nullable V info);
        }

        private interface ListenerWithCancellation<V> extends Listener<V> {
            void cancel();
        }

        /**
         * Default {@code ListenerList} constructor for {@link Executor} based implementation.
         *
         * TODO: consider adding a "name" for debugging if this is used for
         * multiple listener implementations.
         */
        public ListenerList() {
            this(true /* restrictSingleCallerOnEvent */,
                true /* clearCallingIdentity */,
                false /* forceRemoveConsistency*/);
        }

        /**
         * Specific {@code ListenerList} constructor for customization.
         *
         * See the internal notes for the corresponding private variables on the behavior of
         * the boolean configuration parameters.
         *
         * {@code ListenerList(true, true, false)} is the default and used for
         * {@link Executor} based notification implementation.
         *
         * {@code ListenerList(false, false, false)} may be used for as an optimization
         * where the {@link Executor} is actually a {@link Handler} post.
         *
         * @param restrictSingleCallerOnEvent whether the listener will only be called by
         *     a single thread at a time.
         * @param clearCallingIdentity whether the binder calling identity on
         *     {@link #notify} is cleared.
         * @param forceRemoveConsistency whether remove() guarantees no more callbacks to
         *     the listener immediately after the call.
         */
        public ListenerList(boolean restrictSingleCallerOnEvent,
                boolean clearCallingIdentity,
                boolean forceRemoveConsistency) {
            mRestrictSingleCallerOnEvent = restrictSingleCallerOnEvent;
            mClearCallingIdentity = clearCallingIdentity;
            mForceRemoveConsistency = forceRemoveConsistency;
        }

        /**
         * Adds a listener to the {@code ListenerList}.
         *
         * The {@code ListenerList} is most often used to hold {@code multiple} listeners.
         *
         * Per Android style, for a single method Listener interface, the add and remove
         * would be wrapped in "addSomeListener" or "removeSomeListener";
         * or a lambda implemented abstract class callback, wrapped in
         * "registerSomeCallback" or "unregisterSomeCallback".
         *
         * We allow a general {@code key} to be attached to add and remove that specific
         * listener.  It could be the {@code listener} object itself.
         *
         * For some implementations, there may be only a {@code single} listener permitted.
         *
         * Per Android style, for a single listener {@code ListenerList},
         * the naming of the wrapping call to {@link #add} would be
         * "setSomeListener" with a nullable listener, which would be null
         * to call {@link #remove}.
         *
         * In that case, the caller may use this {@link #add} with a single constant object for
         * the {@code key} to enforce only one Listener in the {@code ListenerList}.
         * Likewise on remove it would use that
         * same single constant object to remove the listener.
         * That {@code key} object could be the {@code ListenerList} itself for convenience.
         *
         * @param key is a unique object that is used to identify the listener
         *     when {@code remove()} is called. It can be the listener itself.
         * @param executor is used to execute the callback.
         * @param listener is the {@link AudioTrack.ListenerList.Listener}
         *     interface to be called upon {@link notify}.
         */
        public void add(
                @NonNull Object key, @NonNull Executor executor, @NonNull Listener<V> listener) {
            Objects.requireNonNull(key);
            Objects.requireNonNull(executor);
            Objects.requireNonNull(listener);

            // construct wrapper outside of lock.
            ListenerWithCancellation<V> listenerWithCancellation =
                    new ListenerWithCancellation<V>() {
                        private final Object mLock = new Object(); // our lock is per Listener.
                        private volatile boolean mCancelled = false; // atomic rmw not needed.

                        @Override
                        public void onEvent(int eventCode, V info) {
                            executor.execute(() -> {
                                // Note deep execution of locking and cancellation
                                // so this works after posting on different threads.
                                if (mRestrictSingleCallerOnEvent || mForceRemoveConsistency) {
                                    synchronized (mLock) {
                                        if (mCancelled) return;
                                        listener.onEvent(eventCode, info);
                                    }
                                } else {
                                    if (mCancelled) return;
                                    listener.onEvent(eventCode, info);
                                }
                            });
                        }

                        @Override
                        public void cancel() {
                            if (mForceRemoveConsistency) {
                                synchronized (mLock) {
                                    mCancelled = true;
                                }
                            } else {
                                mCancelled = true;
                            }
                        }
                    };

            synchronized (mListeners) {
                // TODO: consider an option to check the existence of the key
                // and throw an ISE if it exists.
                mListeners.put(key, listenerWithCancellation);  // replaces old value
            }
        }

        /**
         * Removes a listener from the {@code ListenerList}.
         *
         * @param key the unique object associated with the listener during {@link #add}.
         */
        public void remove(@NonNull Object key) {
            Objects.requireNonNull(key);

            ListenerWithCancellation<V> listener;
            synchronized (mListeners) {
                listener = mListeners.get(key);
                if (listener == null) { // TODO: consider an option to throw ISE Here.
                    return;
                }
                mListeners.remove(key);  // removes if exist
            }

            // cancel outside of lock
            listener.cancel();
        }

        /**
         * Notifies all listeners on the List.
         *
         * @param eventCode to pass to all listeners.
         * @param info to pass to all listeners. This is an implemention defined parameter
         *     which may be {@code null}.
         */
        public void notify(int eventCode, @Nullable V info) {
            Object[] listeners; // note we can't cast an object array to a listener array
            synchronized (mListeners) {
                if (mListeners.size() == 0) {
                    return;
                }
                listeners = mListeners.values().toArray(); // guarantees a copy.
            }

            // notify outside of lock.
            final Long identity = mClearCallingIdentity ? Binder.clearCallingIdentity() : null;
            try {
                for (Object object : listeners) {
                    final ListenerWithCancellation<V> listener =
                            (ListenerWithCancellation<V>) object;
                    listener.onEvent(eventCode, info);
                }
            } finally {
                if (identity != null) {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        @GuardedBy("mListeners")
        private HashMap<Object, ListenerWithCancellation<V>> mListeners = new HashMap<>();

        // An Executor may run in multiple threads, whereas a Handler runs on a single Looper.
        // Should be true for an Executor to avoid concurrent calling into the same listener,
        // can be false for a Handler as a Handler forces single thread caller for each listener.
        private final boolean mRestrictSingleCallerOnEvent; // default true

        // An Executor may run in the calling thread, whereas a handler will post to the Looper.
        // Should be true for an Executor to prevent privilege escalation,
        // can be false for a Handler as its thread is not the calling binder thread.
        private final boolean mClearCallingIdentity; // default true

        // Guaranteeing no listener callbacks after removal requires taking the same lock for the
        // remove as the callback; this is a reversal in calling layers,
        // hence the risk of lock order inversion is great.
        //
        // Set to true only if you can control the caller's listen and remove methods and/or
        // the threading of the Executor used for each listener.
        // When set to false, we do not lock, but still do a best effort to cancel messages
        // on the fly.
        private final boolean mForceRemoveConsistency; // default false
    }
}
