package org.opensourcetlapp.tl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;
import org.opensourcetlapp.tl.Adapters.MyPostsAdapter;
import org.opensourcetlapp.tl.Structs.PostInfo;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
public class SearchFragment extends ListFragment implements Runnable {
EditText search;
Fragment instance;
ProgressBar progressBar;
SearchHandler handler;
ArrayList<PostInfo> postInfoList = new ArrayList<PostInfo>();
int page = 1;
private boolean mInstanceAlreadySaved;
private Bundle mSavedOutState;
private DBHelper db;
private String searchType = "t"; // default; t => title, c => content
private int dialogItem = 0;
private String username;
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList("search", postInfoList);
outState.putInt("dialogItem", dialogItem);
outState.putString("username", username);
mInstanceAlreadySaved = true;
}
public ArrayList<PostInfo> getList(Object[] nodeList) throws XPatherException, ArrayIndexOutOfBoundsException {
TagNode n;
Object[] resourceList = null;
for (Object o : nodeList){
n = (TagNode)o;
if (n.evaluateXPath("./td[3]").length > 0) {
TagNode topicStarter = (TagNode)(n.evaluateXPath("./td[3]"))[0];
TagNode replies = (TagNode)(n.evaluateXPath("./td[4]"))[0];
TagNode lastMessage = (TagNode)(n.evaluateXPath("./td[6]"))[0];
resourceList = (n.evaluateXPath("./td[2]/a"));
TagNode topic = (TagNode)resourceList[0];
TagNode lastPost = (TagNode)resourceList[resourceList.length-1];
TagNode topicURL = (TagNode)resourceList[0];
String topicURLString = topicURL.getAttributeByName("href");
if (searchType == "c") {
int postNumber = Integer.parseInt(lastPost.getText().toString());
int pageNumber = (postNumber/20) + 1;
topicURLString = String.format("%s¤tpage=%d#%d", topicURLString, pageNumber, postNumber);
}
PostInfo postInfo = new PostInfo();
if (topicStarter.getChildren().iterator().hasNext())
postInfo.topicStarterString = HtmlTools.unescapeHtml(topicStarter.getChildren().iterator().next().toString());
if (replies.getChildren().iterator().hasNext())
postInfo.repliesString = HtmlTools.unescapeHtml(replies.getChildren().iterator().next().toString());
postInfo.lastMessageString = HtmlTools.unescapeHtml(lastMessage.getChildren().get(0).toString());
postInfo.lastMessageString += " " + HtmlTools.unescapeHtml(lastMessage.getChildren().get(2).toString());
postInfo.topicURL = topicURLString;
if (topic.getChildren().iterator().hasNext())
postInfo.topicString = HtmlTools.unescapeHtml(topic.getChildren().iterator().next().toString());
postInfoList.add(postInfo);
}
}
return postInfoList;
}
public void run() {
try {
TagNode response = TLLib.TagNodeFromURLSearch(new HtmlCleaner(),search.getText().toString()+"&t="+searchType+(username != null ? "&u="+username : ""), handler,getActivity());
Object[] tableResults = null;
Object[] nodeList = null;
try {
tableResults = response.evaluateXPath("//table[@width=748]/tbody");
Log.d("Search", Integer.toString(tableResults.length));
nodeList = ((TagNode)tableResults[tableResults.length - 2]).evaluateXPath("//tr[position()>1]");
postInfoList = getList(nodeList);
} catch (XPatherException e) {
Log.d("SearchFragment", "couldn't retrieve results tables");
e.printStackTrace();
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(0);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onResume() {
super.onResume();
if (!postInfoList.isEmpty())
handler.sendEmptyMessage(0);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (db == null)
db = new DBHelper(getActivity());
if (null == savedInstanceState && null != mSavedOutState) {
savedInstanceState = mSavedOutState;
}
mInstanceAlreadySaved = false;
if (savedInstanceState != null) {
postInfoList = savedInstanceState.getParcelableArrayList("search");
dialogItem = savedInstanceState.getInt("dialogItem");
username = savedInstanceState.getString("username");
}
instance = this;
View view = inflater.inflate(R.layout.search, container, false);
search = (EditText)view.findViewById(R.id.search);
progressBar = (ProgressBar)view.findViewById(R.id.progressBar);
search.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(search.getWindowToken(), 0);
postInfoList = new ArrayList<PostInfo>();
progressBar.setVisibility(View.VISIBLE);
handler = new SearchHandler(progressBar);
page = 1;
new Thread((Runnable)instance).start();
return true;
}
return false;
}
});
return view;
}
public class SearchHandler extends Handler {
private ProgressBar bar;
public SearchHandler(ProgressBar bar) {
this.bar = bar;
}
@Override
public void handleMessage(Message msg) {
if (msg.what == 0 ) {
TextView header = (TextView)getActivity().findViewById(R.id.searchHeader);
ListView list = (ListView)getActivity().findViewById(android.R.id.list);
header.setText("Search by " + (searchType == "t" ? "Title" : "Content") + (username != null ? " - " + username : ""));
list.setAdapter(new MyPostsAdapter(postInfoList, getActivity()));
header.setVisibility(View.VISIBLE);
bar.setVisibility(View.INVISIBLE);
} else {
super.handleMessage(msg);
}
}
}
@Override
public void onStop()
{
if (!mInstanceAlreadySaved)
{
mSavedOutState = new Bundle();
onSaveInstanceState( mSavedOutState );
}
super.onStop();
}
@Override
public void onDestroy(){
super.onDestroy();
db.close();
}
public void onListItemClick(ListView l, View v, int position, long id) {
PostInfo postInfo = postInfoList.get((int) id);
String postURL = "/forum/"+postInfo.topicURL;
String postTopic = postInfo.topicString;
boolean postLocked = postInfo.locked;
Intent intent = new Intent().setClass(getActivity(), ShowThread.class);
intent.putExtra("postURL", postURL);
intent.putExtra("postTopic", postTopic);
intent.putExtra("postLocked", false);
startActivity(intent);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
menuInflater.inflate(R.menu.search_menu, menu);
}
public boolean onOptionsItemSelected(MenuItem item) {
Context context = getActivity();
switch (item.getItemId()) {
case R.id.searchBy:
final CharSequence[] items = {"Title", "Content"};
AlertDialog.Builder builderRadio = new AlertDialog.Builder(context);
builderRadio.setTitle("Search Option");
builderRadio.setSingleChoiceItems(items, dialogItem, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
switch (id) {
case 0:
searchType = "t";
dialogItem = 0;
break;
case 1:
searchType ="c";
dialogItem = 1;
break;
}
Toast.makeText(getActivity(), items[id], Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
AlertDialog alertRadio = builderRadio.create();
alertRadio.show();
break;
case R.id.searchUser:
LayoutInflater li = LayoutInflater.from(context);
View promptsView = li.inflate(R.layout.search_user_prompt, null);
final EditText userInput = (EditText) promptsView.findViewById(R.id.searchUsernameText);
userInput.setText(username);
AlertDialog.Builder builderInput = new AlertDialog.Builder(context);
builderInput.setView(promptsView);
builderInput.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
username = userInput.getText().toString();
}
});
AlertDialog AlertInput = builderInput.create();
AlertInput.show();
break;
}
return true;
}
}