package com.piusvelte.sonet.fragment; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.ListFragment; import android.text.TextUtils; import android.view.ActionMode; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.ListView; import com.piusvelte.sonet.R; import com.piusvelte.sonet.adapter.AccountAdapter; import com.piusvelte.sonet.adapter.PostAccountsAdapter; import com.piusvelte.sonet.loader.AccountsProfilesLoaderCallback; import com.piusvelte.sonet.social.Client; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; /** * Created by bemmanuel on 4/30/15. */ public class ChoosePostAccounts extends ListFragment implements AccountsProfilesLoaderCallback.OnAccountsLoadedListener, AbsListView.MultiChoiceModeListener, PostAccountsAdapter.OnLocationClickListener { private static final String ARG_REQUEST_CODE = "request_code"; private static final String ARG_SELECTED_ACCOUNTS = "selected_accounts"; private static final int LOADER_ACCOUNTS = 0; private static final String DIALOG_CHOOSE_LOCATION = "dialog:choose_location"; private static final int REQUEST_CHOOSE_LOCATION = 0; private View mLoadingView; private List<HashMap<String, String>> mAccounts = new ArrayList<>(); private PostAccountsAdapter mAdapter; public static ChoosePostAccounts newInstance(int requestCode, @NonNull HashSet<Account> selectedAccounts) { ChoosePostAccounts fragment = new ChoosePostAccounts(); Bundle args = new Bundle(); args.putInt(ARG_REQUEST_CODE, requestCode); args.putParcelableArrayList(ARG_SELECTED_ACCOUNTS, new ArrayList<>(selectedAccounts)); fragment.setArguments(args); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.loading_list, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mLoadingView = view.findViewById(R.id.loading); ListView listView = getListView(); listView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL); listView.setMultiChoiceModeListener(this); mAdapter = new PostAccountsAdapter(getActivity(), mAccounts, this); listView.setAdapter(mAdapter); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setHasOptionsMenu(true); mLoadingView.setVisibility(View.VISIBLE); getLoaderManager().initLoader(LOADER_ACCOUNTS, null, new AccountsProfilesLoaderCallback(this, LOADER_ACCOUNTS)); } @Override public void onDestroyView() { mLoadingView = null; super.onDestroyView(); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); menu.clear(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CHOOSE_LOCATION: if (resultCode == Activity.RESULT_OK) { long accountId = ChooseLocation.getAccountId(data); String latitude = ChooseLocation.getLatitude(data); String longitude = ChooseLocation.getLongitude(data); String location = ChooseLocation.getLocation(data); List<Account> selectedAccounts = getArguments().getParcelableArrayList(ARG_SELECTED_ACCOUNTS); for (Account account : selectedAccounts) { if (account.id == accountId) { account.latitude = latitude; account.longitude = longitude; account.location = location; break; } } } break; default: super.onActivityResult(requestCode, resultCode, data); } } @Override public Context getContext() { return getActivity(); } @Override public void onAccountsLoaded(List<HashMap<String, String>> accounts) { if (isAdded()) { mLoadingView.setVisibility(View.GONE); mAdapter.clearSelection(); mAccounts.clear(); if (accounts != null) { mAccounts.addAll(accounts); } mAdapter.notifyDataSetChanged(); if (accounts != null) { List<Account> selection = getArguments().getParcelableArrayList(ARG_SELECTED_ACCOUNTS); if (selection != null) { int position = 0; for (HashMap<String, String> account : accounts) { for (ChoosePostAccounts.Account selectedAccount : selection) { if (AccountAdapter.getAccountId(account) == selectedAccount.id) { getListView().setItemChecked(position, true); } } position++; } } } else { mAdapter.clearSelection(); } } } public static List<Account> getAccounts(@NonNull Intent intent) { return intent.getParcelableArrayListExtra(ARG_SELECTED_ACCOUNTS); } @Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); l.setItemChecked(position, !l.isItemChecked(position)); } @Override public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { List<Account> selectedAccounts = getArguments().getParcelableArrayList(ARG_SELECTED_ACCOUNTS); if (checked) { // don't add if already exists boolean newSelectedAccount = true; // TODO this shouldn't happen :/ for (Account selectedAccount : selectedAccounts) { if (selectedAccount.id == id) { newSelectedAccount = false; break; } } if (newSelectedAccount) { Account account = new Account(); account.id = id; account.service = AccountAdapter.getAccountService(mAdapter.getItem(position)); selectedAccounts.add(account); } } else { ArrayList<Account> newSelectedAccounts = new ArrayList<>(selectedAccounts.size()); for (Account account : selectedAccounts) { if (account.id != id) { newSelectedAccounts.add(account); } } getArguments().putParcelableArrayList(ARG_SELECTED_ACCOUNTS, newSelectedAccounts); selectedAccounts = newSelectedAccounts; } mAdapter.setSelection(position, checked); mAdapter.notifyDataSetChanged(); mode.setTitle(selectedAccounts.size() + " accounts"); } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { int requestCode = getArguments().getInt(ARG_REQUEST_CODE); Intent intent = new Intent().putExtra(ARG_SELECTED_ACCOUNTS, getArguments().getParcelableArrayList(ARG_SELECTED_ACCOUNTS)); Fragment target = getTargetFragment(); if (target != null) { target.onActivityResult(requestCode, Activity.RESULT_OK, intent); } else { Fragment parent = getParentFragment(); if (parent != null) { parent.onActivityResult(requestCode, Activity.RESULT_OK, intent); } else { Activity activity = getActivity(); if (activity instanceof BaseDialogFragment.OnResultListener) { ((BaseDialogFragment.OnResultListener) activity).onResult(requestCode, Activity.RESULT_OK, intent); } } } getFragmentManager().popBackStack(); } @Override public void onLocationClick(int position) { HashMap<String, String> account = mAdapter.getItem(position); if (Client.Network.get(AccountAdapter.getAccountService(account)).isLocationSupported()) { String latitude; String longitude; // TODO FusedLocationProvider LocationManager locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE); Location location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (location != null) { latitude = Double.toString(location.getLatitude()); longitude = Double.toString(location.getLongitude()); } else { latitude = null; longitude = null; } if (!TextUtils.isEmpty(latitude) && !TextUtils.isEmpty(longitude)) { long accountId = AccountAdapter.getAccountId(account); ChooseLocation.newInstance(REQUEST_CHOOSE_LOCATION, accountId, latitude, longitude) .show(getChildFragmentManager(), DIALOG_CHOOSE_LOCATION); } } } public static class Account implements Parcelable { public long id; public int service; public String latitude; public String longitude; public String location; @Nullable public List<String> tags; public Account() { } public Account(Parcel in) { id = in.readLong(); service = in.readInt(); latitude = in.readString(); longitude = in.readString(); location = in.readString(); tags = in.createStringArrayList(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(id); dest.writeInt(service); dest.writeString(latitude); dest.writeString(longitude); dest.writeString(location); dest.writeStringList(tags); } public static final Parcelable.Creator<Account> CREATOR = new Parcelable.Creator<Account>() { @Override public Account createFromParcel(Parcel source) { return new Account(source); } @Override public Account[] newArray(int size) { return new Account[size]; } }; } }