package org.openintents.filemanager.lists;

import java.io.File;
import java.io.IOException;

import org.openintents.filemanager.PreferenceActivity;
import org.openintents.filemanager.compatibility.ActionbarRefreshHelper;
import org.openintents.filemanager.compatibility.FileMultiChoiceModeHelper;
import org.openintents.filemanager.dialogs.CreateDirectoryDialog;
import org.openintents.filemanager.files.FileHolder;
import org.openintents.filemanager.util.CopyHelper;
import org.openintents.filemanager.util.FileUtils;
import org.openintents.filemanager.util.MenuUtils;
import org.openintents.filemanager.view.PathBar;
import org.openintents.filemanager.view.PathBar.Mode;
import org.openintents.filemanager.view.PathBar.OnDirectoryChangedListener;
import org.openintents.intents.FileManagerIntents;

import android.content.Intent;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
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.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
import android.widget.Toast;

import com.sharegogo.wireless.R;
import com.sharegogo.wireless.SharegogoWirelessApp;

/**
 * A file list fragment that supports context menu and CAB selection. 
 * 
 * @author George Venios
 */
public class SimpleFileListFragment extends FileListFragment {
	private static final String INSTANCE_STATE_PATHBAR_MODE = "pathbar_mode";
	
    protected static final int REQUEST_CODE_MULTISELECT = 2;
    
	private PathBar mPathBar;
	private boolean mActionsEnabled = true;
	
	private int mSingleSelectionMenu = R.menu.context;
	private int mMultiSelectionMenu = R.menu.multiselect;
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		return inflater.inflate(R.layout.filelist_browse, null);
	}
	
	@Override
	public void onViewCreated(View view, Bundle savedInstanceState) {
		super.onViewCreated(view, savedInstanceState);
		
		// Pathbar init.
		mPathBar = (PathBar) view.findViewById(R.id.pathbar);
		// Handle mPath differently if we restore state or just initially create the view.
		if(savedInstanceState == null)
			mPathBar.setInitialDirectory(getPath());
		else
			mPathBar.cd(getPath());
		mPathBar.setOnDirectoryChangedListener(new OnDirectoryChangedListener() {

			@Override
			public void directoryChanged(File newCurrentDir) {
				open(new FileHolder(newCurrentDir, getActivity()));
			}
		});
		if(savedInstanceState != null && savedInstanceState.getBoolean(INSTANCE_STATE_PATHBAR_MODE))
			mPathBar.switchToManualInput();
		// Removed else clause as the other mode is the default. It seems faster this way on Nexus S.
		
		initContextualActions();
	}
	
	/**
	 * Override this to handle initialization of list item long clicks.
	 */
	void initContextualActions(){
		if(mActionsEnabled){
			if (VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
				registerForContextMenu(getListView());
			} else {
				FileMultiChoiceModeHelper multiChoiceModeHelper = new FileMultiChoiceModeHelper(mSingleSelectionMenu, mMultiSelectionMenu);
				multiChoiceModeHelper.setListView(getListView());
				multiChoiceModeHelper.setPathBar(mPathBar);
				multiChoiceModeHelper.setContext(this);
				getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
			}
			setHasOptionsMenu(true);
		}
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View view,
			ContextMenuInfo menuInfo) {
		MenuInflater inflater = new MenuInflater(getActivity());

		// Obtain context menu info
		AdapterView.AdapterContextMenuInfo info;
		try {
			info = (AdapterView.AdapterContextMenuInfo) menuInfo;
		} catch (ClassCastException e) {
			e.printStackTrace();
			return;
		}

		MenuUtils.fillContextMenu((FileHolder) mAdapter.getItem(info.position), menu, mSingleSelectionMenu, inflater, getActivity());
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		FileHolder fh = (FileHolder) mAdapter.getItem(((AdapterContextMenuInfo) item.getMenuInfo()).position);
		return MenuUtils.handleSingleSelectionAction(this, item, fh, getActivity());
	}

	@Override
	public void onListItemClick(ListView l, View v, int position, long id) {
		FileHolder item = (FileHolder) mAdapter.getItem(position);
		
		openInformingPathBar(item);
	}

	/**
	 * Use this to open files and folders using this fragment. Appropriately handles pathbar updates.
	 * @param item The dir/file to open.
	 */
	public void openInformingPathBar(FileHolder item) {
		if(mPathBar == null)
			open(item);
		else
			mPathBar.cd(item.getFile());
	}

	/**
	 * Point this Fragment to show the contents of the passed file.
	 * 
	 * @param f If same as current, does nothing.
	 */
	private void open(FileHolder f) {
		if (!f.getFile().exists())
			return;

		if (f.getFile().isDirectory()) {
			openDir(f);
		} else if (f.getFile().isFile()) {
			openFile(f);
		}	
	}
	
	private void openFile(FileHolder fileholder){
		FileUtils.openFile(fileholder, getActivity());
	}
	
	/**
	 * Attempts to open a directory for browsing. 
	 * Override this to handle folder click behavior.
	 * 
	 * @param fileholder The holder of the directory to open.
	 */
	protected void openDir(FileHolder fileholder){
		// Avoid unnecessary attempts to load.
		if(fileholder.getFile().getAbsolutePath().equals(getPath()))
			return;
		
		setPath(fileholder.getFile());
		refresh();
	}
	
	protected void setLongClickMenus(int singleSelectionResource, int multiSelectionResource) {
		mSingleSelectionMenu = singleSelectionResource;
		mMultiSelectionMenu = multiSelectionResource;
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		inflater.inflate(R.menu.simple_file_list, menu);
	}

	@Override
	public void onPrepareOptionsMenu(Menu menu) {
		// We only know about ".nomedia" once scanning is finished.
		boolean showMediaScanMenuItem = PreferenceActivity.getMediaScanFromPreference(getActivity());
		if (!mScanner.isRunning() && showMediaScanMenuItem) {
			menu.findItem(R.id.menu_media_scan_include).setVisible(mScanner.getNoMedia());
			menu.findItem(R.id.menu_media_scan_exclude).setVisible(!mScanner.getNoMedia());
		} else {
			menu.findItem(R.id.menu_media_scan_include).setVisible(false);
			menu.findItem(R.id.menu_media_scan_exclude).setVisible(false);
		}
		
		if(((SharegogoWirelessApp) getActivity().getApplication()).getCopyHelper().canPaste()) {
			menu.findItem(R.id.menu_paste).setVisible(true);
		} else {
			menu.findItem(R.id.menu_paste).setVisible(false);
		}
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		
		case R.id.menu_create_folder:
			CreateDirectoryDialog dialog = new CreateDirectoryDialog();
			dialog.setTargetFragment(this, 0);
			Bundle args = new Bundle();
			args.putString(FileManagerIntents.EXTRA_DIR_PATH, getPath());
			dialog.setArguments(args);
			dialog.show(getActivity().getSupportFragmentManager(), CreateDirectoryDialog.class.getName());
			return true;
			
		case R.id.menu_media_scan_include:
			includeInMediaScan();
			return true;

		case R.id.menu_media_scan_exclude:
			excludeFromMediaScan();
			return true;
			
		case R.id.menu_paste:
			if(((SharegogoWirelessApp) getActivity().getApplication()).getCopyHelper().canPaste())
				((SharegogoWirelessApp) getActivity().getApplication()).getCopyHelper().paste(new File(getPath()), new CopyHelper.OnOperationFinishedListener() {
					@Override
					public void operationFinished(boolean success) {
						refresh();
						
						// Refresh options menu
						if(VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB)
							ActionbarRefreshHelper.activity_invalidateOptionsMenu(getActivity());
					}
				});
			else
				Toast.makeText(getActivity(), R.string.nothing_to_paste, Toast.LENGTH_LONG).show();
			return true;
			
		case R.id.menu_multiselect:
	        Intent intent = new Intent(FileManagerIntents.ACTION_MULTI_SELECT);
	        intent.putExtra(FileManagerIntents.EXTRA_DIR_PATH, getPath());
	        startActivityForResult(intent, REQUEST_CODE_MULTISELECT);
			return true;
			
		default:
			return false;
		}
	}
	
	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		// Automatically refresh to display possible changes done through the multiselect fragment.
		if(requestCode == REQUEST_CODE_MULTISELECT)
			refresh();
		super.onActivityResult(requestCode, resultCode, data);
	}

	private void includeInMediaScan() {
		// Delete the .nomedia file.
		File file = FileUtils.getFile(mPathBar.getCurrentDirectory(),
				FileUtils.NOMEDIA_FILE_NAME);
		if (file.delete()) {
			Toast.makeText(getActivity(),
					getString(R.string.media_scan_included), Toast.LENGTH_LONG)
					.show();
		} else {
			// That didn't work.
			Toast.makeText(getActivity(), getString(R.string.error_generic),
					Toast.LENGTH_LONG).show();
		}
		refresh();
	}

	private void excludeFromMediaScan() {
		// Create the .nomedia file.
		File file = FileUtils.getFile(mPathBar.getCurrentDirectory(),
				FileUtils.NOMEDIA_FILE_NAME);
		try {
			if (file.createNewFile()) {
				Toast.makeText(getActivity(),
						getString(R.string.media_scan_excluded),
						Toast.LENGTH_LONG).show();
			} else {
				Toast.makeText(getActivity(),
						getString(R.string.error_media_scan), Toast.LENGTH_LONG)
						.show();
			}
		} catch (IOException e) {
			// That didn't work.
			Toast.makeText(getActivity(),
					getString(R.string.error_generic) + e.getMessage(), Toast.LENGTH_LONG).show();
		}
		refresh();
	}

	public void browseToHome() {
		mPathBar.cd(mPathBar.getInitialDirectory());
	}

	public boolean pressBack() {
		return mPathBar.pressBack();
	}
	
	/**
	 * Set whether to show menu and selection actions. Must be set before OnViewCreated is called.
	 * @param enabled
	 */
	public void setActionsEnabled(boolean enabled){
		mActionsEnabled = enabled;
	}
	
	@Override
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		
		outState.putBoolean(INSTANCE_STATE_PATHBAR_MODE, mPathBar.getMode() == Mode.MANUAL_INPUT);
	}
}