/*
 * Copyright (C) 2012 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.net.wifi.p2p;

import java.util.Collection;
import java.util.Map;

import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.LruCache;


/**
 * A class representing a Wi-Fi P2p group list
 *
 * {@see WifiP2pManager}
 * @hide
 */
public class WifiP2pGroupList implements Parcelable {

    private static final int CREDENTIAL_MAX_NUM             =   32;

    @UnsupportedAppUsage
    private final LruCache<Integer, WifiP2pGroup> mGroups;
    private final GroupDeleteListener mListener;

    private boolean isClearCalled = false;

    public interface GroupDeleteListener {
        public void onDeleteGroup(int netId);
    }

    /** @hide */
    public WifiP2pGroupList() {
        this(null, null);
    }

    /** @hide */
    @UnsupportedAppUsage
    public WifiP2pGroupList(WifiP2pGroupList source, GroupDeleteListener listener) {
        mListener = listener;
        mGroups = new LruCache<Integer, WifiP2pGroup>(CREDENTIAL_MAX_NUM) {
            @Override
            protected void entryRemoved(boolean evicted, Integer netId,
                    WifiP2pGroup oldValue, WifiP2pGroup newValue) {
                if (mListener != null && !isClearCalled) {
                    mListener.onDeleteGroup(oldValue.getNetworkId());
                }
            }
        };

        if (source != null) {
            for (Map.Entry<Integer, WifiP2pGroup> item : source.mGroups.snapshot().entrySet()) {
                mGroups.put(item.getKey(), item.getValue());
            }
        }
    }

    /**
     * Return the list of p2p group.
     *
     * @return the list of p2p group.
     */
    @UnsupportedAppUsage
    public Collection<WifiP2pGroup> getGroupList() {
        return mGroups.snapshot().values();
    }

    /**
     * Add the specified group to this group list.
     *
     * @param group
     * @hide
     */
    public void add(WifiP2pGroup group) {
        mGroups.put(group.getNetworkId(), group);
    }

    /**
     * Remove the group with the specified network id from this group list.
     *
     * @param netId
     * @hide
     */
    public void remove(int netId) {
        mGroups.remove(netId);
    }

    /**
     * Remove the group with the specified device address from this group list.
     *
     * @param deviceAddress
     */
    void remove(String deviceAddress) {
        remove(getNetworkId(deviceAddress));
    }

    /**
     * Clear the group.
     * @hide
     */
    public boolean clear() {
        if (mGroups.size() == 0) return false;
        isClearCalled = true;
        mGroups.evictAll();
        isClearCalled = false;
        return true;
    }

    /**
     * Return the network id of the group owner profile with the specified p2p device
     * address.
     * If more than one persistent group of the same address is present in the list,
     * return the first one.
     *
     * @param deviceAddress p2p device address.
     * @return the network id. if not found, return -1.
     * @hide
     */
    public int getNetworkId(String deviceAddress) {
        if (deviceAddress == null) return -1;

        final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
        for (WifiP2pGroup grp: groups) {
            if (deviceAddress.equalsIgnoreCase(grp.getOwner().deviceAddress)) {
                // update cache ordered.
                mGroups.get(grp.getNetworkId());
                return grp.getNetworkId();
            }
        }
        return -1;
    }

    /**
     * Return the network id of the group with the specified p2p device address
     * and the ssid.
     *
     * @param deviceAddress p2p device address.
     * @param ssid ssid.
     * @return the network id. if not found, return -1.
     * @hide
     */
    public int getNetworkId(String deviceAddress, String ssid) {
        if (deviceAddress == null || ssid == null) {
            return -1;
        }

        final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
        for (WifiP2pGroup grp: groups) {
            if (deviceAddress.equalsIgnoreCase(grp.getOwner().deviceAddress) &&
                    ssid.equals(grp.getNetworkName())) {
                // update cache ordered.
                mGroups.get(grp.getNetworkId());
                return grp.getNetworkId();
            }
        }

        return -1;
    }

    /**
     * Return the group owner address of the group with the specified network id
     *
     * @param netId network id.
     * @return the address. if not found, return null.
     * @hide
     */
    public String getOwnerAddr(int netId) {
        WifiP2pGroup grp = mGroups.get(netId);
        if (grp != null) {
            return grp.getOwner().deviceAddress;
        }
        return null;
    }

    /**
     * Return true if this group list contains the specified network id.
     * This function does NOT update LRU information.
     * It means the internal queue is NOT reordered.
     *
     * @param netId network id.
     * @return true if the specified network id is present in this group list.
     * @hide
     */
    public boolean contains(int netId) {
        final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
        for (WifiP2pGroup grp: groups) {
            if (netId == grp.getNetworkId()) {
                return true;
            }
        }
        return false;
    }

    public String toString() {
        StringBuffer sbuf = new StringBuffer();

        final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
        for (WifiP2pGroup grp: groups) {
            sbuf.append(grp).append("\n");
        }
        return sbuf.toString();
    }

    /** Implement the Parcelable interface */
    public int describeContents() {
        return 0;
    }

    /** Implement the Parcelable interface */
    public void writeToParcel(Parcel dest, int flags) {
        final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
        dest.writeInt(groups.size());
        for(WifiP2pGroup group : groups) {
            dest.writeParcelable(group, flags);
        }
    }

    /** Implement the Parcelable interface */
    public static final @android.annotation.NonNull Creator<WifiP2pGroupList> CREATOR =
        new Creator<WifiP2pGroupList>() {
            public WifiP2pGroupList createFromParcel(Parcel in) {
                WifiP2pGroupList grpList = new WifiP2pGroupList();

                int deviceCount = in.readInt();
                for (int i = 0; i < deviceCount; i++) {
                    grpList.add((WifiP2pGroup)in.readParcelable(null));
                }
                return grpList;
            }

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