package com.github.andlyticsproject;

import android.annotation.SuppressLint;
import android.support.v7.app.AppCompatActivity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.Html;
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.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.github.andlyticsproject.cache.AppIconInMemoryCache;
import com.github.andlyticsproject.db.AndlyticsDb;
import com.github.andlyticsproject.dialog.AddEditLinkDialog;
import com.github.andlyticsproject.dialog.LongTextDialog;
import com.github.andlyticsproject.model.AppInfo;
import com.github.andlyticsproject.model.Link;
import com.github.andlyticsproject.util.DetachableAsyncTask;
import com.github.andlyticsproject.util.Utils;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;

public class AppInfoActivity extends AppCompatActivity implements
		AddEditLinkDialog.OnFinishAddEditLinkDialogListener, OnItemLongClickListener {

	public static final String TAG = Main.class.getSimpleName();

	private LinksListAdapter linksListAdapter;

	private LoadLinksDb loadLinksDb;

	private AppInfo appInfo;
	private List<Link> links;

	private ListView list;
	private View linksListEmpty;

	private AndlyticsDb db;

	private String packageName;
	private String iconFilePath;

	private ActionMode currentActionMode;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.appinfo);

		Bundle b = getIntent().getExtras();
		if (b != null) {
			packageName = b.getString(BaseActivity.EXTRA_PACKAGE_NAME);
			iconFilePath = b.getString(BaseActivity.EXTRA_ICON_FILE);
		}

		getSupportActionBar().setDisplayHomeAsUpEnabled(true);

		String appName = getDbAdapter().getAppName(packageName);
		if (appName != null) {
			getSupportActionBar().setSubtitle(appName);
		}

		LayoutInflater layoutInflater = getLayoutInflater();

		list = (ListView) findViewById(R.id.appinfo_links_list);

		list.addHeaderView(layoutInflater.inflate(R.layout.appinfo_header, null), null, false);

		list.addFooterView(layoutInflater.inflate(R.layout.appinfo_links_list_empty, null), null,
				false);

		links = new ArrayList<Link>();

		linksListAdapter = new LinksListAdapter(this);
		list.setAdapter(linksListAdapter);
		list.setOnItemLongClickListener(this);

		linksListAdapter.setLinks(links);
		linksListAdapter.notifyDataSetChanged();

		View playStoreButton = findViewById(R.id.appinfo_playstore);

		playStoreButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent intent = new Intent(Intent.ACTION_VIEW);
				intent.setData(Uri.parse("https://play.google.com/store/apps/details?id="
						+ packageName));
				startActivity(intent);
			}
		});

		db = AndlyticsDb.getInstance(this);

		loadLinksDb = new LoadLinksDb(this);
		Utils.execute(loadLinksDb);

		registerForContextMenu(list);
	}

	@Override
	public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
		if (currentActionMode != null) {
			return false;
		}

		// skip header
		if (position == 0) {
			return false;
		}

		currentActionMode = startActionMode(new ContextCallback(position));
		list.setItemChecked(position, true);

		return true;
	}

	@SuppressLint("NewApi")
	class ContextCallback implements ActionMode.Callback {

		private int position;

		ContextCallback(int position) {
			this.position = position;
		}

		public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
			MenuInflater inflater = getMenuInflater();
			inflater.inflate(R.menu.links_context_menu, menu);
			return true;
		}

		public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
			return false;
		}

		public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {

			if (menuItem.getItemId() == R.id.itemLinksmenuEdit) {
				int pos = position - 1; // Subtract one for the header
				Link link = links.get(pos);

				showAddEditLinkDialog(link);
				actionMode.finish();
				return true;
			} else if (menuItem.getItemId() == R.id.itemLinksmenuDelete) {
				int pos = position - 1; // Subtract one for the header
				Link link = links.get(pos);

				db.deleteLink(link.getId().longValue());

				loadLinksDb = new LoadLinksDb(AppInfoActivity.this);
				Utils.execute(loadLinksDb);
				actionMode.finish();
				return true;
			}

			return false;
		}

		public void onDestroyActionMode(ActionMode actionMode) {
			list.setItemChecked(position, false);
			currentActionMode = null;
		}
	};

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.clear();
		getMenuInflater().inflate(R.menu.links_menu, menu);

		return true;
	}

	/**
	 * Called if item in option menu is selected.
	 * 
	 * @param item
	 * The chosen menu item
	 * @return boolean true/false
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			finish();
			overridePendingTransition(R.anim.activity_prev_in, R.anim.activity_prev_out);
			return true;
		case R.id.itemLinksmenuAdd:
			showAddEditLinkDialog(null);
			return true;
		default:
			return (super.onOptionsItemSelected(item));
		}
	}

	@Override
	public void onBackPressed() {
		finish();
		overridePendingTransition(R.anim.activity_prev_in, R.anim.activity_prev_out);
	}

	public ContentAdapter getDbAdapter() {
		return getAndlyticsApplication().getDbAdapter();
	}

	public AndlyticsApp getAndlyticsApplication() {
		return (AndlyticsApp) getApplication();
	}

	private static class LoadLinksDb extends DetachableAsyncTask<Void, Void, Void, AppInfoActivity> {

		LoadLinksDb(AppInfoActivity activity) {
			super(activity);
		}

		@Override
		protected Void doInBackground(Void... params) {
			if (activity == null) {
				return null;
			}

			activity.getLinksFromDb();

			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			if (activity == null) {
				return;
			}

			activity.refreshLinks();
		}

	}

	private void getLinksFromDb() {
		appInfo = db.findAppByPackageName(packageName);
		links = appInfo == null ? new ArrayList<Link>() : appInfo.getDetails().getLinks();
	}

	private void refreshLinks() {
		linksListAdapter.setLinks(links);
		linksListAdapter.notifyDataSetChanged();

		linksListEmpty = findViewById(R.id.appinfo_links_list_empty);

		if (links.size() == 0) {
			linksListEmpty.setVisibility(View.VISIBLE);
		} else {
			linksListEmpty.setVisibility(View.GONE);
		}

		ImageView iconView = (ImageView) findViewById(R.id.appinfo_app_icon);
		String packageName = appInfo.getPackageName();
		// XXX hack? should be cached on main screen, so don't bother trying to load
		//		if (inMemoryCache.contains(packageName)) {
		iconView.setImageBitmap(AppIconInMemoryCache.getInstance().get(packageName));
		iconView.clearAnimation();

		TextView appNameView = (TextView) findViewById(R.id.appinfo_app_name);
		appNameView.setText(appInfo.getName());

		TextView packageNameView = (TextView) findViewById(R.id.appinfo_package_name);
		packageNameView.setText(packageName);

		TextView developerView = (TextView) findViewById(R.id.appinfo_developer);
		developerView.setText(String.format("%s / %s", appInfo.getDeveloperName(),
				appInfo.getDeveloperId()));

		TextView versionNameView = (TextView) findViewById(R.id.appinfo_version_name);
		versionNameView.setText(appInfo.getVersionName());

		TextView lastStoreUpdateView = (TextView) findViewById(R.id.appinfo_last_store_update);
		lastStoreUpdateView.setText(DateFormat.getDateInstance().format(
				appInfo.getDetails().getLastStoreUpdate()));

		TextView descriptionView = (TextView) findViewById(R.id.appinfo_description);
		final String description = appInfo.getDetails().getDescription().replace("\n", "<br/>");
		descriptionView.setText(Html.fromHtml(description));
		descriptionView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				showLongTextDialog(R.string.appinfo_description_label, description);
			}
		});

		TextView changelogView = (TextView) findViewById(R.id.appinfo_changelog);
		final String changelog = appInfo.getDetails().getChangelog().replace("\n", "<br/>");
		changelogView.setText(Html.fromHtml(changelog));
		changelogView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				showLongTextDialog(R.string.appinfo_changelog_label, changelog);
			}
		});
	}

	@Override
	public void onFinishAddEditLink(String url, String name, Long id) {
		if (id == null) {
			db.addLink(appInfo.getDetails(), url, name);
		} else {
			db.editLink(id, url, name);
		}

		loadLinksDb = new LoadLinksDb(this);
		Utils.execute(loadLinksDb);
	}

	private void showAddEditLinkDialog(Link link) {
		FragmentTransaction ft = getFragmentManager().beginTransaction();
		Fragment prev = getFragmentManager().findFragmentByTag("fragment_addedit_link");
		if (prev != null) {
			ft.remove(prev);
		}
		ft.addToBackStack(null);

		AddEditLinkDialog addEditLinkDialog = new AddEditLinkDialog();

		Bundle arguments = new Bundle();
		if (link != null) {
			arguments.putLong("id", link.getId().longValue());
			arguments.putString("name", link.getName());
			arguments.putString("url", link.getURL());
		}

		addEditLinkDialog.setArguments(arguments);

		addEditLinkDialog.setOnFinishAddEditLinkDialogListener(this);

		addEditLinkDialog.show(ft, "fragment_addedit_link");
	}

	private void showLongTextDialog(int title, String longText) {
		FragmentTransaction ft = getFragmentManager().beginTransaction();
		Fragment prev = getFragmentManager().findFragmentByTag("fragment_longtext");
		if (prev != null) {
			ft.remove(prev);
		}
		ft.addToBackStack(null);

		LongTextDialog longTextDialog = new LongTextDialog();

		Bundle arguments = new Bundle();
		arguments.putInt("title", title);
		arguments.putString("longText", longText);

		longTextDialog.setArguments(arguments);

		longTextDialog.show(ft, "fragment_longtext");
	}
}
