package com.github.andlyticsproject;

import android.support.v7.app.AppCompatActivity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.github.andlyticsproject.cache.AppIconInMemoryCache;
import com.github.andlyticsproject.io.ExportService;
import com.github.andlyticsproject.io.StatsCsvReaderWriter;
import com.github.andlyticsproject.model.AppInfo;
import com.github.andlyticsproject.util.DetachableAsyncTask;
import com.github.andlyticsproject.util.Utils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class ExportActivity extends AppCompatActivity {

	private static final String TAG = ExportActivity.class.getSimpleName();

	public static final int TAG_IMAGE_REF = R.id.tag_mainlist_image_reference;

	public static final String EXTRA_ACCOUNT_NAME = "accountName";
	private static final String EXTRA_EXPORT_PACKAGE_NAMES = "exportPackageNames";

	private LayoutInflater layoutInflater;

	private AppIconInMemoryCache inMemoryCache;

	private File cacheDir;

	private Drawable spacerIcon;

	private ExportListAdapter adapter;
	private List<AppInfo> appInfos = new ArrayList<AppInfo>();
	private ArrayList<String> exportPackageNames = new ArrayList<String>();
	private String accountName;

	private LoadExportTask loadTask;

	@SuppressWarnings("unchecked")
	@Override
	public void onCreate(Bundle state) {
		super.onCreate(state);

		setContentView(R.layout.export_stats);
		setProgressBarIndeterminateVisibility(false);

		layoutInflater = getLayoutInflater();

		accountName = getIntent().getExtras().getString(EXTRA_ACCOUNT_NAME);
		getSupportActionBar().setSubtitle(accountName);
		getSupportActionBar().setDisplayHomeAsUpEnabled(true);

		adapter = new ExportListAdapter();
		setAppInfos(appInfos);

		if (state != null) {
			exportPackageNames = (ArrayList<String>) state
					.getSerializable(EXTRA_EXPORT_PACKAGE_NAMES);
		}

		setupView();

		this.inMemoryCache = AppIconInMemoryCache.getInstance();
		this.cacheDir = getCacheDir();
		this.spacerIcon = ContextCompat.getDrawable(this, R.drawable.app_icon_spacer);

		if (getLastNonConfigurationInstance() != null) {
			loadTask = (LoadExportTask) getLastNonConfigurationInstance();
			loadTask.attach(this);
			setAppInfos(loadTask.getAppInfos());
		} else {
			loadTask = new LoadExportTask(this);
			Utils.execute(loadTask);
		}
	}

	private void setupView() {
		View closeButton = (View) this.findViewById(R.id.export_dialog_close_button);
		closeButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				finish();
			}
		});

		final Context context = this;
		View exportButton = (View) this.findViewById(R.id.export_dialog_export_button);
		exportButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				if (!android.os.Environment.getExternalStorageState().equals(
						android.os.Environment.MEDIA_MOUNTED)) {
					Toast.makeText(context, context.getString(R.string.export_no_sdcard),
							Toast.LENGTH_LONG).show();

					return;
				}

				if (exportPackageNames.isEmpty()) {
					Toast.makeText(context, context.getString(R.string.export_no_app),
							Toast.LENGTH_LONG).show();

					return;
				}

				String accountName = DeveloperAccountManager.getInstance(ExportActivity.this)
						.getSelectedDeveloperAccount().getName();
				File exportFile = StatsCsvReaderWriter.getExportFileForAccount(accountName);
				if (exportFile.exists()) {
					ConfirmExportDialogFragment.newInstance(exportFile.getName()).show(
							getFragmentManager(), "confirmExportDialog");
				} else {
					startExport();
				}
			}
		});

		ListView lv = (ListView) this.findViewById(R.id.list_view_id);
		lv.addHeaderView(layoutInflater.inflate(R.layout.export_list_header, null));
		lv.setAdapter(adapter);
	}

	@Override
	protected void onSaveInstanceState(Bundle state) {
		super.onSaveInstanceState(state);
		state.putSerializable(EXTRA_EXPORT_PACKAGE_NAMES, exportPackageNames);
	}


	@Override
	public Object onRetainCustomNonConfigurationInstance() {
		return loadTask == null ? null : loadTask.detach();
	}

	String getAccountName() {
		return accountName;
	}

	public static class ConfirmExportDialogFragment extends DialogFragment {

		public static final String ARG_FILENAME = "filename";

		public static ConfirmExportDialogFragment newInstance(String filename) {
			ConfirmExportDialogFragment frag = new ConfirmExportDialogFragment();
			Bundle args = new Bundle();
			args.putString(ARG_FILENAME, filename);
			frag.setArguments(args);
			return frag;
		}

		@Override
		public Dialog onCreateDialog(Bundle savedInstanceState) {
			final String filename = getArguments().getString(ARG_FILENAME);

			return new AlertDialog.Builder(getActivity())
					.setIcon(android.R.drawable.ic_dialog_alert)
					.setTitle(R.string.export_confirm_dialog_title)
					.setMessage(
							getResources().getString(R.string.export_confirm_dialog_message,
									filename))
					.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int whichButton) {
							((ExportActivity) getActivity()).startExport();
						}
					})
					.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int whichButton) {
							dismiss();
						}
					}).create();
		}
	}


	private static class LoadExportTask extends
			DetachableAsyncTask<Void, Void, List<AppInfo>, ExportActivity> {

		ContentAdapter db;
		List<AppInfo> appInfos = new ArrayList<AppInfo>();

		LoadExportTask(ExportActivity parent) {
			super(parent);
			db = ContentAdapter.getInstance(parent.getApplication());
		}

		@Override
		protected void onPreExecute() {
			activity.setProgressBarIndeterminateVisibility(true);
		}

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

			try {
				appInfos = db.getAllAppsLatestStats(activity.getAccountName());

				return appInfos;
			} catch (Exception e) {
				Log.e(TAG, "Failed to get app stats: " + e.getMessage(), e);

				return null;
			}
		}

		@Override
		protected void onPostExecute(List<AppInfo> result) {
			if (activity == null) {
				return;
			}

			activity.setProgressBarIndeterminateVisibility(false);

			if (!activity.isFinishing()) {
				if (result != null) {
					activity.setAppInfos(result);
				} else {
					Toast.makeText(activity, R.string.export_failed_to_load_stats,
							Toast.LENGTH_LONG).show();
					activity.finish();
				}
			}
		}

		List<AppInfo> getAppInfos() {
			return appInfos;
		}

	}

	class ExportListAdapter extends BaseAdapter {

		@Override
		public int getCount() {
			return getAppInfos().size();
		}

		@Override
		public AppInfo getItem(int position) {
			return getAppInfos().get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {

			ViewHolder holder;

			if (convertView == null) {

				convertView = layoutInflater.inflate(R.layout.export_list_item, null);

				holder = new ViewHolder();
				holder.name = (TextView) convertView.findViewById(R.id.main_app_name);
				holder.packageName = (TextView) convertView.findViewById(R.id.main_package_name);
				holder.icon = (ImageView) convertView.findViewById(R.id.main_app_icon);
				holder.row = (RelativeLayout) convertView.findViewById(R.id.main_app_row);
				holder.checkbox = (CheckBox) convertView.findViewById(R.id.ghost_checkbox);
				convertView.setTag(holder);

			} else {
				holder = (ViewHolder) convertView.getTag();
			}

			final AppInfo appDownloadInfo = getItem(position);
			holder.name.setText(appDownloadInfo.getName());
			holder.packageName.setText(appDownloadInfo.getPackageName());

			final String packageName = appDownloadInfo.getPackageName();

			holder.checkbox.setChecked(exportPackageNames.contains(packageName));

			final File iconFile = new File(cacheDir + "/" + appDownloadInfo.getIconName());

			holder.icon.setTag(TAG_IMAGE_REF, packageName);
			if (inMemoryCache.contains(packageName)) {

				holder.icon.setImageBitmap(inMemoryCache.get(packageName));
				holder.icon.clearAnimation();

			} else {
				holder.icon.setImageDrawable(null);
				holder.icon.clearAnimation();
				new GetCachedImageTask(holder.icon, appDownloadInfo.getPackageName())
						.execute(new File[] { iconFile });
			}

			holder.row.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {

					CheckBox checkbox = ((CheckBox) (((ViewGroup) v)
							.findViewById(R.id.ghost_checkbox)));
					checkbox.setChecked(!checkbox.isChecked());

					if (checkbox.isChecked()) {
						exportPackageNames.add(appDownloadInfo.getPackageName());
					} else {
						exportPackageNames.remove(appDownloadInfo.getPackageName());
					}

				}
			});

			holder.checkbox.setTag(packageName);
			holder.checkbox.setOnClickListener(new CheckBox.OnClickListener() {

				@Override
				public void onClick(View v) {
					boolean checked = ((CheckBox) v).isChecked();
					if (checked) {
						exportPackageNames.add(appDownloadInfo.getPackageName());
					} else {
						exportPackageNames.remove(appDownloadInfo.getPackageName());
					}

				}
			});

			return convertView;
		}

		private class ViewHolder {
			public RelativeLayout row;
			public TextView name;
			public TextView packageName;
			public ImageView icon;
			public CheckBox checkbox;
		}
	}

	private class GetCachedImageTask extends AsyncTask<File, Void, Bitmap> {

		private ImageView imageView;
		private String reference;

		public GetCachedImageTask(ImageView imageView, String reference) {
			this.imageView = imageView;
			this.reference = reference;
		}

		protected void onPostExecute(Bitmap result) {

			// only update the image if tag==reference
			// (view may have been reused as convertView)
			if (imageView.getTag(TAG_IMAGE_REF).equals(reference)) {

				if (result == null) {
					imageView.setImageDrawable(spacerIcon);
				} else {
					inMemoryCache.put(reference, result);
					updateMainImage(imageView, R.anim.fade_in_fast, result);
				}
			}
		}

		@Override
		protected Bitmap doInBackground(File... params) {

			File iconFile = params[0];

			if (iconFile.exists()) {
				Bitmap bm = BitmapFactory.decodeFile(iconFile.getAbsolutePath());
				return bm;
			}
			return null;
		}
	}

	public void updateMainImage(ImageView imageView, int animationId, Bitmap result) {
		imageView.setImageBitmap(result);
		imageView.clearAnimation();
		Animation fadeInAnimation = AnimationUtils.loadAnimation(getApplicationContext(),
				animationId);
		imageView.startAnimation(fadeInAnimation);
	}

	public void setAppInfos(List<AppInfo> appInfos) {
		this.appInfos = appInfos;
		if (adapter != null) {
			this.adapter.notifyDataSetChanged();
		}
	}

	public List<AppInfo> getAppInfos() {
		return appInfos;
	}

	private void startExport() {
		Intent exportIntent = new Intent(this, ExportService.class);
		exportIntent.putExtra(ExportService.EXTRA_PACKAGE_NAMES,
				exportPackageNames.toArray(new String[exportPackageNames.size()]));
		exportIntent.putExtra(ExportService.EXTRA_ACCOUNT_NAME, accountName);
		startService(exportIntent);

		finish();
	}
}
