1/*
2* Copyright (C) 2014 Samsung System LSI
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7*      http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15
16package com.android.bluetooth.map;
17
18import java.util.ArrayList;
19import java.util.HashMap;
20import java.util.LinkedHashMap;
21import java.util.List;
22import java.util.Map;
23
24import com.android.bluetooth.R;
25import android.app.Activity;
26import android.content.ContentResolver;
27import android.content.ContentValues;
28import android.graphics.drawable.Drawable;
29import android.net.Uri;
30import android.os.Handler;
31import com.android.bluetooth.mapapi.BluetoothMapContract;
32import android.util.Log;
33import android.util.SparseArray;
34import android.view.LayoutInflater;
35import android.view.View;
36import android.view.View.OnClickListener;
37import android.view.ViewGroup;
38import android.widget.BaseExpandableListAdapter;
39import android.widget.CheckBox;
40import android.widget.CheckedTextView;
41import android.widget.CompoundButton.OnCheckedChangeListener;
42import android.widget.ExpandableListView;
43import android.widget.ExpandableListView.OnGroupExpandListener;
44import android.widget.ImageView;
45import android.widget.TextView;
46import android.widget.Toast;
47import android.widget.CompoundButton;
48import com.android.bluetooth.map.BluetoothMapAccountItem;
49import com.android.bluetooth.map.BluetoothMapAccountLoader;
50public class BluetoothMapSettingsAdapter extends BaseExpandableListAdapter {
51    private static final boolean D = BluetoothMapService.DEBUG;
52    private static final boolean V = BluetoothMapService.VERBOSE;
53    private static final String TAG = "BluetoothMapSettingsAdapter";
54    private boolean mCheckAll = true;
55    public LayoutInflater mInflater;
56    public Activity mActivity;
57    /*needed to prevent random checkbox toggles due to item reuse */
58    ArrayList<Boolean> mPositionArray;
59    private LinkedHashMap<BluetoothMapAccountItem,
60                            ArrayList<BluetoothMapAccountItem>> mProupList;
61    private ArrayList<BluetoothMapAccountItem> mMainGroup;
62    private int[] mGroupStatus;
63    /* number of accounts possible to share */
64    private int mSlotsLeft = 10;
65
66
67    public BluetoothMapSettingsAdapter(Activity act,
68                                            ExpandableListView listView,
69                                            LinkedHashMap<BluetoothMapAccountItem,
70                                              ArrayList<BluetoothMapAccountItem>> groupsList,
71                                            int enabledAccountsCounts) {
72        mActivity = act;
73        this.mProupList = groupsList;
74        mInflater = act.getLayoutInflater();
75        mGroupStatus = new int[groupsList.size()];
76        mSlotsLeft = mSlotsLeft-enabledAccountsCounts;
77
78        listView.setOnGroupExpandListener(new OnGroupExpandListener() {
79
80            public void onGroupExpand(int groupPosition) {
81                BluetoothMapAccountItem group = mMainGroup.get(groupPosition);
82                if (mProupList.get(group).size() > 0)
83                    mGroupStatus[groupPosition] = 1;
84
85            }
86        });
87        mMainGroup = new ArrayList<BluetoothMapAccountItem>();
88        for (Map.Entry<BluetoothMapAccountItem,
89                ArrayList<BluetoothMapAccountItem>> mapEntry : mProupList.entrySet()) {
90            mMainGroup.add(mapEntry.getKey());
91        }
92    }
93
94    @Override
95    public BluetoothMapAccountItem getChild(int groupPosition, int childPosition) {
96        BluetoothMapAccountItem item = mMainGroup.get(groupPosition);
97        return mProupList.get(item).get(childPosition);
98    }
99    private ArrayList<BluetoothMapAccountItem> getChild(BluetoothMapAccountItem group) {
100        return mProupList.get(group);
101    }
102
103    @Override
104    public long getChildId(int groupPosition, int childPosition) {
105        return 0;
106    }
107
108    @Override
109    public View getChildView(final int groupPosition, final int childPosition,
110            boolean isLastChild, View convertView, ViewGroup parent) {
111
112
113        final ChildHolder holder;
114        if (convertView == null) {
115            convertView = mInflater.inflate(R.layout.bluetooth_map_settings_account_item, null);
116            holder = new ChildHolder();
117            holder.cb = (CheckBox) convertView.findViewById(R.id.bluetooth_map_settings_item_check);
118            holder.title =
119                (TextView) convertView.findViewById(R.id.bluetooth_map_settings_item_text_view);
120            convertView.setTag(holder);
121        } else {
122            holder = (ChildHolder) convertView.getTag();
123        }
124            final BluetoothMapAccountItem child =  getChild(groupPosition, childPosition);
125            holder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
126
127                public void onCheckedChanged(CompoundButton buttonView,
128                        boolean isChecked) {
129                    BluetoothMapAccountItem parentGroup =
130                          (BluetoothMapAccountItem)getGroup(groupPosition);
131                    boolean oldIsChecked = child.mIsChecked; // needed to prevent updates on UI redraw
132                    child.mIsChecked = isChecked;
133                    if (isChecked) {
134                        ArrayList<BluetoothMapAccountItem> childList = getChild(parentGroup);
135                        int childIndex = childList.indexOf(child);
136                        boolean isAllChildClicked = true;
137                        if(mSlotsLeft-childList.size() >=0){
138
139                            for (int i = 0; i < childList.size(); i++) {
140                                if (i != childIndex) {
141                                    BluetoothMapAccountItem siblings = childList.get(i);
142                                    if (!siblings.mIsChecked) {
143                                        isAllChildClicked = false;
144                                            BluetoothMapSettingsDataHolder.mCheckedChilds.put(
145                                                child.getName(), parentGroup.getName());
146                                        break;
147
148                                    }
149                                }
150                            }
151                        }else {
152                            showWarning(mActivity.getString(
153                                R.string.bluetooth_map_settings_no_account_slots_left));
154                            isAllChildClicked = false;
155                            child.mIsChecked = false;
156                        }
157                        if (isAllChildClicked) {
158                            parentGroup.mIsChecked = true;
159                            if(!(BluetoothMapSettingsDataHolder.mCheckedChilds.containsKey(
160                                child.getName())==true)){
161                                BluetoothMapSettingsDataHolder.mCheckedChilds.put(child.getName(),
162                                        parentGroup.getName());
163                            }
164                            mCheckAll = false;
165                        }
166
167
168                    } else {
169                        if (parentGroup.mIsChecked) {
170                            parentGroup.mIsChecked = false;
171                            mCheckAll = false;
172                            BluetoothMapSettingsDataHolder.mCheckedChilds.remove(child.getName());
173                        } else {
174                            mCheckAll = true;
175                            BluetoothMapSettingsDataHolder.mCheckedChilds.remove(child.getName());
176                        }
177                        // child.isChecked =false;
178                    }
179                    notifyDataSetChanged();
180                    if(child.mIsChecked != oldIsChecked){
181                        updateAccount(child);
182                    }
183
184                }
185
186            });
187
188            holder.cb.setChecked(child.mIsChecked);
189            holder.title.setText(child.getName());
190            if(D)Log.i("childs are", BluetoothMapSettingsDataHolder.mCheckedChilds.toString());
191            return convertView;
192
193    }
194
195
196
197    @Override
198    public int getChildrenCount(int groupPosition) {
199        BluetoothMapAccountItem item = mMainGroup.get(groupPosition);
200        return mProupList.get(item).size();
201    }
202
203    @Override
204    public BluetoothMapAccountItem getGroup(int groupPosition) {
205        return mMainGroup.get(groupPosition);
206    }
207
208    @Override
209    public int getGroupCount() {
210        return mMainGroup.size();
211    }
212
213    @Override
214    public void onGroupCollapsed(int groupPosition) {
215        super.onGroupCollapsed(groupPosition);
216    }
217
218    @Override
219    public void onGroupExpanded(int groupPosition) {
220        super.onGroupExpanded(groupPosition);
221    }
222
223    @Override
224    public long getGroupId(int groupPosition) {
225        return 0;
226    }
227
228    @Override
229    public View getGroupView(int groupPosition, boolean isExpanded,
230            View convertView, ViewGroup parent) {
231
232        final GroupHolder holder;
233
234        if (convertView == null) {
235            convertView = mInflater.inflate(R.layout.bluetooth_map_settings_account_group, null);
236            holder = new GroupHolder();
237            holder.cb =
238                (CheckBox) convertView.findViewById(R.id.bluetooth_map_settings_group_checkbox);
239            holder.imageView = (ImageView) convertView
240                    .findViewById(R.id.bluetooth_map_settings_group_icon);
241            holder.title =
242                (TextView) convertView.findViewById(R.id.bluetooth_map_settings_group_text_view);
243            convertView.setTag(holder);
244        } else {
245            holder = (GroupHolder) convertView.getTag();
246        }
247
248        final BluetoothMapAccountItem groupItem = getGroup(groupPosition);
249        holder.imageView.setImageDrawable(groupItem.getIcon());
250
251
252        holder.title.setText(groupItem.getName());
253
254        holder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
255
256            public void onCheckedChanged(CompoundButton buttonView,
257                    boolean isChecked) {
258                if (mCheckAll) {
259                    ArrayList<BluetoothMapAccountItem> childItem = getChild(groupItem);
260                    for (BluetoothMapAccountItem children : childItem)
261                    {
262                        boolean oldIsChecked = children.mIsChecked;
263                        if(mSlotsLeft >0){
264                            children.mIsChecked = isChecked;
265                            if(oldIsChecked != children.mIsChecked){
266                                updateAccount(children);
267                            }
268                        }else {
269                            showWarning(mActivity.getString(
270                                    R.string.bluetooth_map_settings_no_account_slots_left));
271                            isChecked = false;
272                        }
273                    }
274                }
275                groupItem.mIsChecked = isChecked;
276                notifyDataSetChanged();
277                new Handler().postDelayed(new Runnable() {
278
279                    public void run() {
280                        if (!mCheckAll)
281                            mCheckAll = true;
282                    }
283                }, 50);
284
285            }
286
287        });
288        holder.cb.setChecked(groupItem.mIsChecked);
289        return convertView;
290
291    }
292
293    @Override
294    public boolean hasStableIds() {
295        return true;
296    }
297
298    @Override
299    public boolean isChildSelectable(int groupPosition, int childPosition) {
300        return true;
301    }
302
303    private class GroupHolder {
304        public ImageView imageView;
305        public CheckBox cb;
306        public TextView title;
307
308    }
309
310    private class ChildHolder {
311        public TextView title;
312        public CheckBox cb;
313    }
314    public void updateAccount(BluetoothMapAccountItem account) {
315        updateSlotCounter(account.mIsChecked);
316        if(D)Log.d(TAG,"Updating account settings for "
317                +account.getName() +". Value is:"+account.mIsChecked);
318        ContentResolver mResolver = mActivity.getContentResolver();
319        Uri uri = Uri.parse(account.mBase_uri_no_account+"/"+BluetoothMapContract.TABLE_ACCOUNT);
320        ContentValues values = new ContentValues();
321        values.put(BluetoothMapContract.AccountColumns.FLAG_EXPOSE, ((account.mIsChecked)?1:0));
322        values.put(BluetoothMapContract.AccountColumns._ID, account.getId()); // get title
323        mResolver.update(uri, values, null ,null);
324
325    }
326    private void updateSlotCounter(boolean isChecked){
327        if(isChecked)
328        {
329            mSlotsLeft--;
330        }else {
331            mSlotsLeft++;
332        }
333        CharSequence text;
334
335        if (mSlotsLeft <=0)
336        {
337            text = mActivity.getString(R.string.bluetooth_map_settings_no_account_slots_left);
338        }else {
339            text= mActivity.getString(R.string.bluetooth_map_settings_count)
340                + " "+ String.valueOf(mSlotsLeft);
341        }
342
343        int duration = Toast.LENGTH_SHORT;
344
345        Toast toast = Toast.makeText(mActivity, text, duration);
346        toast.show();
347    }
348    private void showWarning(String text){
349        int duration = Toast.LENGTH_SHORT;
350
351        Toast toast = Toast.makeText(mActivity, text, duration);
352        toast.show();
353
354    }
355
356
357}
358