/*
 * 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 com.android.systemui.statusbar.phone;

import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;

import android.annotation.NonNull;
import android.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

public class StatusBarIconList {
    private ArrayList<Slot> mSlots = new ArrayList<>();

    public StatusBarIconList(String[] slots) {
        final int N = slots.length;
        for (int i=0; i < N; i++) {
            mSlots.add(new Slot(slots[i], null));
        }
    }

    public int getSlotIndex(String slot) {
        final int N = mSlots.size();
        for (int i=0; i<N; i++) {
            Slot item = mSlots.get(i);
            if (item.getName().equals(slot)) {
                return i;
            }
        }
        // Auto insert new items at the beginning.
        mSlots.add(0, new Slot(slot, null));
        return 0;
    }

    protected ArrayList<Slot> getSlots() {
        return new ArrayList<>(mSlots);
    }

    protected Slot getSlot(String name) {
        return mSlots.get(getSlotIndex(name));
    }

    public int size() {
        return mSlots.size();
    }

    public void setIcon(int index, @NonNull StatusBarIconHolder holder) {
        mSlots.get(index).addHolder(holder);
    }

    public void removeIcon(int index, int tag) {
        mSlots.get(index).removeForTag(tag);
    }

    public String getSlotName(int index) {
        return mSlots.get(index).getName();
    }

    public StatusBarIconHolder getIcon(int index, int tag) {
        return mSlots.get(index).getHolderForTag(tag);
    }

    public int getViewIndex(int slotIndex, int tag) {
        int count = 0;
        for (int i = 0; i < slotIndex; i++) {
            Slot item = mSlots.get(i);
            if (item.hasIconsInSlot()) {
                count += item.numberOfIcons();
            }
        }

        Slot viewItem = mSlots.get(slotIndex);
        return count + viewItem.viewIndexOffsetForTag(tag);
    }

    public void dump(PrintWriter pw) {
        pw.println("StatusBarIconList state:");
        final int N = mSlots.size();
        pw.println("  icon slots: " + N);
        for (int i=0; i<N; i++) {
            pw.printf("    %2d:%s\n", i, mSlots.get(i).toString());
        }
    }

    public static class Slot {
        private final String mName;
        private StatusBarIconHolder mHolder;
        /**
         * Only used if multiple icons are added to the same slot.
         *
         * If there are mSubSlots, then these are structured like:
         *      [ First item | (the rest) ]
         *
         * The tricky thing to keep in mind here is that the list [mHolder, mSubSlots] is ordered
         * ascending, but for view logic we should go backwards through the list. I.e., the first
         * element (mHolder) should be the highest index, because higher priority items go to the
         * right of lower priority items
         */
        private ArrayList<StatusBarIconHolder> mSubSlots;

        public Slot(String name, StatusBarIconHolder iconHolder) {
            mName = name;
            mHolder = iconHolder;
        }

        public String getName() {
            return mName;
        }

        @Nullable
        public StatusBarIconHolder getHolderForTag(int tag) {
            if (tag == TAG_PRIMARY) {
                return mHolder;
            }

            if (mSubSlots != null) {
                for (StatusBarIconHolder holder : mSubSlots) {
                    if (holder.getTag() == tag) {
                        return holder;
                    }
                }
            }

            return null;
        }

        public void addHolder(StatusBarIconHolder holder) {
            int tag = holder.getTag();
            if (tag == TAG_PRIMARY) {
                mHolder = holder;
            } else {
                setSubSlot(holder, tag);
            }
        }

        public void removeForTag(int tag) {
            if (tag == TAG_PRIMARY) {
                mHolder = null;
            } else {
                int index = getIndexForTag(tag);
                if (index != -1) {
                    mSubSlots.remove(index);
                }
            }
        }

        @VisibleForTesting
        public void clear() {
            mHolder = null;
            if (mSubSlots != null) {
                mSubSlots = null;
            }
        }

        private void setSubSlot(StatusBarIconHolder holder, int tag) {
            if (mSubSlots == null) {
                mSubSlots = new ArrayList<>();
                mSubSlots.add(holder);
                return;
            }

            if (getIndexForTag(tag) != -1) {
                // Holder exists for tag; no-op
                return;
            }

            // These holders get added to the end. Confused yet?
            mSubSlots.add(holder);
        }

        private int getIndexForTag(int tag) {
            for (int i = 0; i < mSubSlots.size(); i++) {
                StatusBarIconHolder h = mSubSlots.get(i);
                if (h.getTag() == tag) {
                    return i;
                }
            }

            return -1;
        }

        public boolean hasIconsInSlot() {
            if (mHolder != null) return true;
            if (mSubSlots == null) return false;

            return mSubSlots.size() > 0;
        }

        public int numberOfIcons() {
            int num = mHolder == null ? 0 : 1;
            if (mSubSlots == null) return num;

            return num + mSubSlots.size();
        }

        /**
         * View index is inverted from regular index, because they are laid out back-to-front
         * @param tag the tag of the holder being viewed
         * @return (1 + mSubSlots.size() - indexOfTag)
         */
        public int viewIndexOffsetForTag(int tag) {
            if (mSubSlots == null) {
                return 0;
            }

            int subSlots = mSubSlots.size();
            if (tag == TAG_PRIMARY) {
                return subSlots;
            }

            return subSlots - getIndexForTag(tag) - 1;
        }

        /**
         * Build a list of the {@link StatusBarIconHolder}s in the same order they appear in their
         * view group. This provides a safe list that can be iterated and inserted into its group.
         *
         * @return all holders contained here, in view order
         */
        public List<StatusBarIconHolder> getHolderListInViewOrder() {
            ArrayList<StatusBarIconHolder> holders = new ArrayList<>();
            if (mSubSlots != null) {
                for (int i = mSubSlots.size() - 1; i >= 0; i--) {
                    holders.add(mSubSlots.get(i));
                }
            }

            if (mHolder != null) {
                holders.add(mHolder);
            }

            return holders;
        }

        @Override
        public String toString() {
            return String.format("(%s) %s", mName, subSlotsString());
        }

        private String subSlotsString() {
            if (mSubSlots == null) {
                return "";
            }

            return "" + mSubSlots.size() + " subSlots";
        }
    }
}
