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