package what.whatandroid.search;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.*;
import api.search.user.UserSearch;
import what.whatandroid.R;
import what.whatandroid.callbacks.OnLoggedInCallback;
import what.whatandroid.callbacks.SetTitleCallback;
import what.whatandroid.callbacks.ViewUserCallbacks;
/**
* Fragment for searching for users. If only one user is returned as a result we go to their profile,
* otherwise a list of found users is displayed
*/
public class UserSearchFragment extends Fragment implements View.OnClickListener, TextView.OnEditorActionListener,
OnLoggedInCallback, LoaderManager.LoaderCallbacks<UserSearch>, AbsListView.OnScrollListener {
/**
* So we can set the action bar title and viewing a user
*/
private SetTitleCallback setTitle;
private ViewUserCallbacks viewUser;
/**
* Search terms sent to us through the intent
*/
private String searchTerms;
/**
* The first page of the user search results
*/
private UserSearch userSearch;
/**
* The search terms input box
*/
private EditText editTerms;
/**
* The list of search results and the search result adapter
*/
private UserSearchAdapter resultsAdapter;
/**
* The loading status footer
*/
private View footer;
private TextView noResults;
/**
* Create a user search fragment and have it start lodaing the search desired then the view
* is created. If the terms are empty then no search will be launched
*
* @param terms terms to search users for
* @return the user search fragment
*/
public static UserSearchFragment newInstance(String terms){
UserSearchFragment f = new UserSearchFragment();
Bundle args = new Bundle();
args.putString(SearchActivity.TERMS, terms);
f.setArguments(args);
return f;
}
public UserSearchFragment(){
//Required empty ctor
}
@Override
public void onAttach(Activity activity){
super.onAttach(activity);
try {
setTitle = (SetTitleCallback)activity;
viewUser = (ViewUserCallbacks)activity;
}
catch (ClassCastException e){
throw new ClassCastException(activity.toString() + " must implement SetTitle and ViewUser callbacks");
}
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
if (savedInstanceState == null){
searchTerms = getArguments().getString(SearchActivity.TERMS, "");
}
else {
searchTerms = savedInstanceState.getString(SearchActivity.TERMS, "");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
setTitle.setTitle("User Search");
View view = inflater.inflate(R.layout.fragment_list_view, container, false);
ListView resultsList = (ListView)view.findViewById(R.id.list);
noResults = (TextView)view.findViewById(R.id.no_content_notice);
noResults.setText("No Results");
View header = inflater.inflate(R.layout.header_search, null);
editTerms = (EditText)header.findViewById(R.id.search_terms);
editTerms.setOnEditorActionListener(this);
//Hide the unneeded tags box
header.findViewById(R.id.search_tags).setVisibility(View.GONE);
Button search = (Button)header.findViewById(R.id.search_button);
search.setOnClickListener(this);
footer = inflater.inflate(R.layout.footer_loading_indicator, null);
resultsList.addHeaderView(header);
resultsList.addFooterView(footer);
resultsList.setFooterDividersEnabled(false);
footer.setVisibility(View.GONE);
resultsAdapter = new UserSearchAdapter(getActivity(), footer);
resultsList.setAdapter(resultsAdapter);
resultsList.setOnItemClickListener(resultsAdapter);
resultsList.setOnScrollListener(this);
if (searchTerms.isEmpty()){
editTerms.requestFocus();
}
else {
editTerms.setText(searchTerms);
}
return view;
}
@Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
outState.putString(SearchActivity.TERMS, editTerms.getText().toString());
}
@Override
public void onLoggedIn(){
//Don't auto-search since this fragment redirects to user's profile if we only
//get one result
}
@Override
public void onClick(View v){
searchTerms = editTerms.getText().toString();
if (!searchTerms.isEmpty()){
InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editTerms.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
resultsAdapter.clear();
resultsAdapter.notifyDataSetChanged();
footer.setVisibility(View.VISIBLE);
startSearch(searchTerms, 1);
}
else {
Toast.makeText(getActivity(), "Enter search terms", Toast.LENGTH_SHORT).show();
editTerms.requestFocus();
}
}
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event){
if (event == null || event.getAction() == KeyEvent.ACTION_DOWN){
searchTerms = editTerms.getText().toString();
if (!searchTerms.isEmpty()){
InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editTerms.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
resultsAdapter.clear();
resultsAdapter.notifyDataSetChanged();
footer.setVisibility(View.VISIBLE);
startSearch(searchTerms, 1);
}
else {
Toast.makeText(getActivity(), "Enter search terms", Toast.LENGTH_SHORT).show();
editTerms.requestFocus();
}
}
return true;
}
@Override
public Loader<UserSearch> onCreateLoader(int id, Bundle args){
return new UserSearchAsyncLoader(getActivity(), args);
}
@Override
public void onLoadFinished(Loader<UserSearch> loader, UserSearch data){
userSearch = data;
if (userSearch != null){
if (isAdded()){
//If there's only one user in the search go view their profile
if (userSearch.getResponse().getResults().size() == 1){
resultsAdapter.clear();
resultsAdapter.notifyDataSetChanged();
footer.setVisibility(View.GONE);
viewUser.viewUser(userSearch.getResponse().getResults().get(0).getUserId().intValue());
}
else {
if (userSearch.getResponse().getResults().isEmpty()){
noResults.setVisibility(View.VISIBLE);
}
if (userSearch.getPage() == 1){
resultsAdapter.clear();
}
resultsAdapter.addAll(userSearch.getResponse().getResults());
resultsAdapter.notifyDataSetChanged();
if (!userSearch.hasNextPage()){
footer.setVisibility(View.GONE);
}
}
}
}
else if (isAdded()){
Toast.makeText(getActivity(), "Could not load search results", Toast.LENGTH_LONG).show();
footer.setVisibility(View.GONE);
}
}
@Override
public void onLoaderReset(Loader<UserSearch> loader){
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState){
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount){
if (userSearch != null && userSearch.hasNextPage() && firstVisibleItem + visibleItemCount + 10 >= totalItemCount){
startSearch(searchTerms, userSearch.getPage() + 1);
}
}
private void startSearch(String terms, int page){
noResults.setVisibility(View.GONE);
Bundle args = new Bundle();
args.putString(SearchActivity.TERMS, terms);
args.putInt(SearchActivity.PAGE, page);
LoaderManager lm = getLoaderManager();
Loader l = lm.getLoader(page);
if (l == null){
lm.initLoader(page, args, this);
}
//Check if the terms and tags are different from what the loader has and restart if they're different
else {
UserSearchAsyncLoader s = (UserSearchAsyncLoader)l;
if (!s.getTerms().equalsIgnoreCase(searchTerms)){
lm.restartLoader(page, args, this);
}
else {
lm.initLoader(page, args, this);
}
}
}
}