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

import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Represents a Bluetooth GATT Service
 *
 * <p> Gatt Service contains a collection of {@link BluetoothGattCharacteristic},
 * as well as referenced services.
 */
public class BluetoothGattService implements Parcelable {

    /**
     * Primary service
     */
    public static final int SERVICE_TYPE_PRIMARY = 0;

    /**
     * Secondary service (included by primary services)
     */
    public static final int SERVICE_TYPE_SECONDARY = 1;


    /**
     * The remote device his service is associated with.
     * This applies to client applications only.
     *
     * @hide
     */
    @UnsupportedAppUsage
    protected BluetoothDevice mDevice;

    /**
     * The UUID of this service.
     *
     * @hide
     */
    protected UUID mUuid;

    /**
     * Instance ID for this service.
     *
     * @hide
     */
    protected int mInstanceId;

    /**
     * Handle counter override (for conformance testing).
     *
     * @hide
     */
    protected int mHandles = 0;

    /**
     * Service type (Primary/Secondary).
     *
     * @hide
     */
    protected int mServiceType;

    /**
     * List of characteristics included in this service.
     */
    protected List<BluetoothGattCharacteristic> mCharacteristics;

    /**
     * List of included services for this service.
     */
    protected List<BluetoothGattService> mIncludedServices;

    /**
     * Whether the service uuid should be advertised.
     */
    private boolean mAdvertisePreferred;

    /**
     * Create a new BluetoothGattService.
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param uuid The UUID for this service
     * @param serviceType The type of this service,
     * {@link BluetoothGattService#SERVICE_TYPE_PRIMARY}
     * or {@link BluetoothGattService#SERVICE_TYPE_SECONDARY}
     */
    public BluetoothGattService(UUID uuid, int serviceType) {
        mDevice = null;
        mUuid = uuid;
        mInstanceId = 0;
        mServiceType = serviceType;
        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
        mIncludedServices = new ArrayList<BluetoothGattService>();
    }

    /**
     * Create a new BluetoothGattService
     *
     * @hide
     */
    /*package*/ BluetoothGattService(BluetoothDevice device, UUID uuid,
            int instanceId, int serviceType) {
        mDevice = device;
        mUuid = uuid;
        mInstanceId = instanceId;
        mServiceType = serviceType;
        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
        mIncludedServices = new ArrayList<BluetoothGattService>();
    }

    /**
     * Create a new BluetoothGattService
     *
     * @hide
     */
    public BluetoothGattService(UUID uuid, int instanceId, int serviceType) {
        mDevice = null;
        mUuid = uuid;
        mInstanceId = instanceId;
        mServiceType = serviceType;
        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
        mIncludedServices = new ArrayList<BluetoothGattService>();
    }

    /**
     * @hide
     */
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeParcelable(new ParcelUuid(mUuid), 0);
        out.writeInt(mInstanceId);
        out.writeInt(mServiceType);
        out.writeTypedList(mCharacteristics);

        ArrayList<BluetoothGattIncludedService> includedServices =
                new ArrayList<BluetoothGattIncludedService>(mIncludedServices.size());
        for (BluetoothGattService s : mIncludedServices) {
            includedServices.add(new BluetoothGattIncludedService(s.getUuid(),
                    s.getInstanceId(), s.getType()));
        }
        out.writeTypedList(includedServices);
    }

    public static final Parcelable.Creator<BluetoothGattService> CREATOR =
            new Parcelable.Creator<BluetoothGattService>() {
        public BluetoothGattService createFromParcel(Parcel in) {
            return new BluetoothGattService(in);
        }

        public BluetoothGattService[] newArray(int size) {
            return new BluetoothGattService[size];
        }
    };

    private BluetoothGattService(Parcel in) {
        mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
        mInstanceId = in.readInt();
        mServiceType = in.readInt();

        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();

        ArrayList<BluetoothGattCharacteristic> chrcs =
                in.createTypedArrayList(BluetoothGattCharacteristic.CREATOR);
        if (chrcs != null) {
            for (BluetoothGattCharacteristic chrc : chrcs) {
                chrc.setService(this);
                mCharacteristics.add(chrc);
            }
        }

        mIncludedServices = new ArrayList<BluetoothGattService>();

        ArrayList<BluetoothGattIncludedService> inclSvcs =
                in.createTypedArrayList(BluetoothGattIncludedService.CREATOR);
        if (chrcs != null) {
            for (BluetoothGattIncludedService isvc : inclSvcs) {
                mIncludedServices.add(new BluetoothGattService(null, isvc.getUuid(),
                        isvc.getInstanceId(), isvc.getType()));
            }
        }
    }

    /**
     * Returns the device associated with this service.
     *
     * @hide
     */
    /*package*/ BluetoothDevice getDevice() {
        return mDevice;
    }

    /**
     * Returns the device associated with this service.
     *
     * @hide
     */
    /*package*/ void setDevice(BluetoothDevice device) {
        mDevice = device;
    }

    /**
     * Add an included service to this service.
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param service The service to be added
     * @return true, if the included service was added to the service
     */
    public boolean addService(BluetoothGattService service) {
        mIncludedServices.add(service);
        return true;
    }

    /**
     * Add a characteristic to this service.
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param characteristic The characteristics to be added
     * @return true, if the characteristic was added to the service
     */
    public boolean addCharacteristic(BluetoothGattCharacteristic characteristic) {
        mCharacteristics.add(characteristic);
        characteristic.setService(this);
        return true;
    }

    /**
     * Get characteristic by UUID and instanceId.
     *
     * @hide
     */
    /*package*/ BluetoothGattCharacteristic getCharacteristic(UUID uuid, int instanceId) {
        for (BluetoothGattCharacteristic characteristic : mCharacteristics) {
            if (uuid.equals(characteristic.getUuid())
                    && characteristic.getInstanceId() == instanceId) {
                return characteristic;
            }
        }
        return null;
    }

    /**
     * Force the instance ID.
     *
     * @hide
     */
    @UnsupportedAppUsage
    public void setInstanceId(int instanceId) {
        mInstanceId = instanceId;
    }

    /**
     * Get the handle count override (conformance testing.
     *
     * @hide
     */
    /*package*/ int getHandles() {
        return mHandles;
    }

    /**
     * Force the number of handles to reserve for this service.
     * This is needed for conformance testing only.
     *
     * @hide
     */
    public void setHandles(int handles) {
        mHandles = handles;
    }

    /**
     * Add an included service to the internal map.
     *
     * @hide
     */
    public void addIncludedService(BluetoothGattService includedService) {
        mIncludedServices.add(includedService);
    }

    /**
     * Returns the UUID of this service
     *
     * @return UUID of this service
     */
    public UUID getUuid() {
        return mUuid;
    }

    /**
     * Returns the instance ID for this service
     *
     * <p>If a remote device offers multiple services with the same UUID
     * (ex. multiple battery services for different batteries), the instance
     * ID is used to distuinguish services.
     *
     * @return Instance ID of this service
     */
    public int getInstanceId() {
        return mInstanceId;
    }

    /**
     * Get the type of this service (primary/secondary)
     */
    public int getType() {
        return mServiceType;
    }

    /**
     * Get the list of included GATT services for this service.
     *
     * @return List of included services or empty list if no included services were discovered.
     */
    public List<BluetoothGattService> getIncludedServices() {
        return mIncludedServices;
    }

    /**
     * Returns a list of characteristics included in this service.
     *
     * @return Characteristics included in this service
     */
    public List<BluetoothGattCharacteristic> getCharacteristics() {
        return mCharacteristics;
    }

    /**
     * Returns a characteristic with a given UUID out of the list of
     * characteristics offered by this service.
     *
     * <p>This is a convenience function to allow access to a given characteristic
     * without enumerating over the list returned by {@link #getCharacteristics}
     * manually.
     *
     * <p>If a remote service offers multiple characteristics with the same
     * UUID, the first instance of a characteristic with the given UUID
     * is returned.
     *
     * @return GATT characteristic object or null if no characteristic with the given UUID was
     * found.
     */
    public BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
        for (BluetoothGattCharacteristic characteristic : mCharacteristics) {
            if (uuid.equals(characteristic.getUuid())) {
                return characteristic;
            }
        }
        return null;
    }

    /**
     * Returns whether the uuid of the service should be advertised.
     *
     * @hide
     */
    public boolean isAdvertisePreferred() {
        return mAdvertisePreferred;
    }

    /**
     * Set whether the service uuid should be advertised.
     *
     * @hide
     */
    @UnsupportedAppUsage
    public void setAdvertisePreferred(boolean advertisePreferred) {
        mAdvertisePreferred = advertisePreferred;
    }
}
