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

import android.annotation.NonNull;
import android.media.AudioFormat;
import android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import java.util.ArrayList;
import java.util.Objects;

/**
 * @hide
 * Internal storage class for AudioPolicy configuration.
 */
public class AudioPolicyConfig implements Parcelable {

    private static final String TAG = "AudioPolicyConfig";

    protected final ArrayList<AudioMix> mMixes;
    protected int mDuckingPolicy = AudioPolicy.FOCUS_POLICY_DUCKING_IN_APP;

    private String mRegistrationId = null;

    /** counter for the mixes that are / have been in the list of AudioMix
     *  e.g. register 4 mixes (counter is 3), remove 1 (counter is 3), add 1 (counter is 4)
     */
    private int mMixCounter = 0;

    protected AudioPolicyConfig(AudioPolicyConfig conf) {
        mMixes = conf.mMixes;
    }

    AudioPolicyConfig(ArrayList<AudioMix> mixes) {
        mMixes = mixes;
    }

    /**
     * Add an {@link AudioMix} to be part of the audio policy being built.
     * @param mix a non-null {@link AudioMix} to be part of the audio policy.
     * @return the same Builder instance.
     * @throws IllegalArgumentException
     */
    public void addMix(AudioMix mix) throws IllegalArgumentException {
        if (mix == null) {
            throw new IllegalArgumentException("Illegal null AudioMix argument");
        }
        mMixes.add(mix);
    }

    public ArrayList<AudioMix> getMixes() {
        return mMixes;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mMixes);
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mMixes.size());
        for (AudioMix mix : mMixes) {
            // write mix route flags
            dest.writeInt(mix.getRouteFlags());
            // write callback flags
            dest.writeInt(mix.mCallbackFlags);
            // write device information
            dest.writeInt(mix.mDeviceSystemType);
            dest.writeString(mix.mDeviceAddress);
            // write mix format
            dest.writeInt(mix.getFormat().getSampleRate());
            dest.writeInt(mix.getFormat().getEncoding());
            dest.writeInt(mix.getFormat().getChannelMask());
            // write opt-out respect
            dest.writeBoolean(mix.getRule().allowPrivilegedPlaybackCapture());
            // write voice communication capture allowed flag
            dest.writeBoolean(mix.getRule().voiceCommunicationCaptureAllowed());
            // write mix rules
            final ArrayList<AudioMixMatchCriterion> criteria = mix.getRule().getCriteria();
            dest.writeInt(criteria.size());
            for (AudioMixMatchCriterion criterion : criteria) {
                criterion.writeToParcel(dest);
            }
        }
    }

    private AudioPolicyConfig(Parcel in) {
        mMixes = new ArrayList<AudioMix>();
        int nbMixes = in.readInt();
        for (int i = 0 ; i < nbMixes ; i++) {
            final AudioMix.Builder mixBuilder = new AudioMix.Builder();
            // read mix route flags
            int routeFlags = in.readInt();
            mixBuilder.setRouteFlags(routeFlags);
            // read callback flags
            mixBuilder.setCallbackFlags(in.readInt());
            // read device information
            mixBuilder.setDevice(in.readInt(), in.readString());
            // read mix format
            int sampleRate = in.readInt();
            int encoding = in.readInt();
            int channelMask = in.readInt();
            final AudioFormat format = new AudioFormat.Builder().setSampleRate(sampleRate)
                    .setChannelMask(channelMask).setEncoding(encoding).build();
            mixBuilder.setFormat(format);

            AudioMixingRule.Builder ruleBuilder = new AudioMixingRule.Builder();
            // read opt-out respect
            ruleBuilder.allowPrivilegedPlaybackCapture(in.readBoolean());
            // read voice capture allowed flag
            ruleBuilder.voiceCommunicationCaptureAllowed(in.readBoolean());
            // read mix rules
            int nbRules = in.readInt();
            for (int j = 0 ; j < nbRules ; j++) {
                // read the matching rules
                ruleBuilder.addRuleFromParcel(in);
            }
            mixBuilder.setMixingRule(ruleBuilder.build());
            mMixes.add(mixBuilder.build());
        }
    }

    public static final @android.annotation.NonNull Parcelable.Creator<AudioPolicyConfig> CREATOR
            = new Parcelable.Creator<AudioPolicyConfig>() {
        /**
         * Rebuilds an AudioPolicyConfig previously stored with writeToParcel().
         * @param p Parcel object to read the AudioPolicyConfig from
         * @return a new AudioPolicyConfig created from the data in the parcel
         */
        public AudioPolicyConfig createFromParcel(Parcel p) {
            return new AudioPolicyConfig(p);
        }
        public AudioPolicyConfig[] newArray(int size) {
            return new AudioPolicyConfig[size];
        }
    };

    public String toLogFriendlyString () {
        String textDump = new String("android.media.audiopolicy.AudioPolicyConfig:\n");
        textDump += mMixes.size() + " AudioMix: "+ mRegistrationId + "\n";
        for(AudioMix mix : mMixes) {
            // write mix route flags
            textDump += "* route flags=0x" + Integer.toHexString(mix.getRouteFlags()) + "\n";
            // write mix format
            textDump += "  rate=" + mix.getFormat().getSampleRate() + "Hz\n";
            textDump += "  encoding=" + mix.getFormat().getEncoding() + "\n";
            textDump += "  channels=0x";
            textDump += Integer.toHexString(mix.getFormat().getChannelMask()).toUpperCase() + "\n";
            textDump += "  ignore playback capture opt out="
                    + mix.getRule().allowPrivilegedPlaybackCapture() + "\n";
            textDump += "  allow voice communication capture="
                    + mix.getRule().voiceCommunicationCaptureAllowed() + "\n";
            // write mix rules
            final ArrayList<AudioMixMatchCriterion> criteria = mix.getRule().getCriteria();
            for (AudioMixMatchCriterion criterion : criteria) {
                switch(criterion.mRule) {
                    case AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_USAGE:
                        textDump += "  exclude usage ";
                        textDump += criterion.mAttr.usageToString();
                        break;
                    case AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE:
                        textDump += "  match usage ";
                        textDump += criterion.mAttr.usageToString();
                        break;
                    case AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET:
                        textDump += "  exclude capture preset ";
                        textDump += criterion.mAttr.getCapturePreset();
                        break;
                    case AudioMixingRule.RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
                        textDump += "  match capture preset ";
                        textDump += criterion.mAttr.getCapturePreset();
                        break;
                    case AudioMixingRule.RULE_MATCH_UID:
                        textDump += "  match UID ";
                        textDump += criterion.mIntProp;
                        break;
                    case AudioMixingRule.RULE_EXCLUDE_UID:
                        textDump += "  exclude UID ";
                        textDump += criterion.mIntProp;
                        break;
                    case AudioMixingRule.RULE_MATCH_USERID:
                        textDump += "  match userId ";
                        textDump += criterion.mIntProp;
                        break;
                    case AudioMixingRule.RULE_EXCLUDE_USERID:
                        textDump += "  exclude userId ";
                        textDump += criterion.mIntProp;
                        break;
                    default:
                        textDump += "invalid rule!";
                }
                textDump += "\n";
            }
        }
        return textDump;
    }

    protected void setRegistration(String regId) {
        final boolean currentRegNull = (mRegistrationId == null) || mRegistrationId.isEmpty();
        final boolean newRegNull = (regId == null) || regId.isEmpty();
        if (!currentRegNull && !newRegNull && !mRegistrationId.equals(regId)) {
            Log.e(TAG, "Invalid registration transition from " + mRegistrationId + " to " + regId);
            return;
        }
        mRegistrationId = regId == null ? "" : regId;
        for (AudioMix mix : mMixes) {
            setMixRegistration(mix);
        }
    }

    private void setMixRegistration(@NonNull final AudioMix mix) {
        if (!mRegistrationId.isEmpty()) {
            if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) ==
                    AudioMix.ROUTE_FLAG_LOOP_BACK) {
                mix.setRegistration(mRegistrationId + "mix" + mixTypeId(mix.getMixType()) + ":"
                        + mMixCounter);
            } else if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_RENDER) ==
                    AudioMix.ROUTE_FLAG_RENDER) {
                mix.setRegistration(mix.mDeviceAddress);
            }
        } else {
            mix.setRegistration("");
        }
        mMixCounter++;
    }

    @GuardedBy("mMixes")
    protected void add(@NonNull ArrayList<AudioMix> mixes) {
        for (AudioMix mix : mixes) {
            setMixRegistration(mix);
            mMixes.add(mix);
        }
    }

    @GuardedBy("mMixes")
    protected void remove(@NonNull ArrayList<AudioMix> mixes) {
        for (AudioMix mix : mixes) {
            mMixes.remove(mix);
        }
    }

    private static String mixTypeId(int type) {
        if (type == AudioMix.MIX_TYPE_PLAYERS) return "p";
        else if (type == AudioMix.MIX_TYPE_RECORDERS) return "r";
        else return "i";
    }

    protected String getRegistration() {
        return mRegistrationId;
    }
}
