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.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.github.andlyticsproject.io.ImportService;
import com.github.andlyticsproject.io.ServiceException;
import com.github.andlyticsproject.io.StatsCsvReaderWriter;
import com.github.andlyticsproject.util.DetachableAsyncTask;
import com.github.andlyticsproject.util.FileUtils;
import com.github.andlyticsproject.util.Utils;

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

public class ImportActivity extends AppCompatActivity {

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

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

	private static final String EXTRA_IMPORT_FILENAMES = "importFilenames";

	private ImportListAdapter adapter;

	private LayoutInflater layoutInflater;

	private ArrayList<String> importFilenames = new ArrayList<String>();

	private String accountName;

	private ListView listView;

	private LoadImportDialogTask loadTask;

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

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

		layoutInflater = getLayoutInflater();

		accountName = getAccountName();
		getSupportActionBar().setSubtitle(accountName);

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

		setupViews();

		if (Intent.ACTION_VIEW.equals(getIntent().getAction())) {
			Uri data = getIntent().getData();
			if (data == null) {
				Toast.makeText(this, getString(R.string.stats_file_not_specified_error),
						Toast.LENGTH_LONG).show();
				finish();
			}

			if (getLastNonConfigurationInstance() != null) {
				loadTask = (LoadImportDialogTask) getLastNonConfigurationInstance();
				loadTask.attach(this);
				setFilenames(loadTask.getFilenames());
			} else {
				loadTask = new LoadImportDialogTask(this, accountName);
				Utils.execute(loadTask, data);
			}
		} else {
			Log.w(TAG, "Don't know how to handle this action: " + getIntent().getAction());
			finish();
		}
	}

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

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

	private void setupViews() {
		View closeButton = (View) this.findViewById(R.id.import_dialog_close_button);
		closeButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				finish();
			}
		});

		View importButton = (View) this.findViewById(R.id.import_dialog_import_button);
		importButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (importFilenames.isEmpty()) {
					Toast.makeText(ImportActivity.this, getString(R.string.import_no_app),
							Toast.LENGTH_LONG).show();
					return;
				}

				ConfirmImportDialogFragment.newInstance(adapter.getCount()).show(
						getFragmentManager(), "confirmImportDialog");
			}
		});

		listView = (ListView) this.findViewById(R.id.list_view_id);
		listView.addHeaderView(layoutInflater.inflate(R.layout.import_list_header, null), null,
				false);
		setFilenames(new ArrayList<String>());
	}

	void setFilenames(List<String> filenames) {
		adapter = new ImportListAdapter(filenames);
		listView.setAdapter(adapter);
	}

	private String getAccountName() {
		String ownerAccount = StatsCsvReaderWriter.getAccountNameForExport(new File(getIntent()
				.getData().getPath()).getName());
		if (ownerAccount == null) {
			// fall back to value from preferences
			// XXX should we give a choice instead?
			ownerAccount = DeveloperAccountManager.getInstance(this).getSelectedDeveloperAccount()
					.getName();
		}
		return ownerAccount;
	}

	private void startImport() {
		Intent intent = new Intent(ImportActivity.this, ImportService.class);
		intent.setData(getIntent().getData());
		intent.putExtra(ImportService.FILE_NAMES,
				importFilenames.toArray(new String[importFilenames.size()]));
		intent.putExtra(ImportService.ACCOUNT_NAME, accountName);
		startService(intent);
		finish();
	}

	public static class ConfirmImportDialogFragment extends DialogFragment {

		public static final String ARG_NUM_APPS = "numApps";

		public static ConfirmImportDialogFragment newInstance(int numExistingApps) {
			ConfirmImportDialogFragment frag = new ConfirmImportDialogFragment();
			Bundle args = new Bundle();
			args.putInt(ARG_NUM_APPS, numExistingApps);
			frag.setArguments(args);
			return frag;
		}

		@Override
		public Dialog onCreateDialog(Bundle savedInstanceState) {
			final int numExistingApps = getArguments().getInt(ARG_NUM_APPS);

			return new AlertDialog.Builder(getActivity())
					.setIcon(android.R.drawable.ic_dialog_alert)
					.setTitle(R.string.import_confirm_dialog_title)
					.setMessage(
							getResources().getString(R.string.import_confirm_dialog_message,
									numExistingApps))
					.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int whichButton) {
							((ImportActivity) getActivity()).startImport();
						}
					})
					.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int whichButton) {
							dismiss();
						}
					}).create();
		}
	}


	private static class LoadImportDialogTask extends
			DetachableAsyncTask<Uri, Void, Boolean, ImportActivity> {

		ContentAdapter db;
		String accountName;

		LoadImportDialogTask(ImportActivity parent, String accountName) {
			super(parent);
			this.accountName = accountName;
			db = ContentAdapter.getInstance(parent.getApplication());
		}

		private List<String> filenames = new ArrayList<String>();
		private Uri zipFileUri;

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

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

			zipFileUri = params[0];
			List<String> pacakgeNames = db.getPackagesForAccount(accountName);
			try {
				String zipFilePath = zipFileUri.getPath();
				File tempZip = null;
				try {
					if (!zipFileUri.getScheme().equalsIgnoreCase("file")) {
						tempZip = copyToTempFile();
						zipFilePath = tempZip.getAbsolutePath();
					}
					filenames = StatsCsvReaderWriter.getImportFileNamesFromZip(
							activity.getAccountName(), pacakgeNames, zipFilePath);
				} catch (IOException e) {
					Log.e(TAG, "Error reading import zip file: " + e.getMessage());
					return false;
				} finally {
					if (tempZip != null) {
						tempZip.delete();
					}
				}

				return true;
			} catch (ServiceException e) {
				Log.e(TAG, "Error reading import zip file: " + e.getMessage());
				return false;
			}
		}

		private File copyToTempFile() throws IOException {
			File tempZip = File.createTempFile("andlytics-import", ".zip");
			FileOutputStream out = new FileOutputStream(tempZip);
			byte[] zipBytes = FileUtils.readFromUri(activity, zipFileUri);
			out.write(zipBytes);
			out.flush();
			out.close();

			return tempZip;
		}

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

			activity.setProgressBarIndeterminateVisibility(false);

			if (!activity.isFinishing()) {
				if (result) {
					activity.setFilenames(filenames);
				} else {
					Toast.makeText(activity, activity.getString(R.string.import_no_sdcard_or_file),
							Toast.LENGTH_LONG).show();
					activity.finish();
				}
			}
		}

		List<String> getFilenames() {
			return filenames;
		}

	}

	class ImportListAdapter extends BaseAdapter {

		List<String> files;

		ImportListAdapter(List<String> files) {
			this.files = files;
		}

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

		@Override
		public String getItem(int position) {
			return files.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.import_list_item, null);

				holder = new ViewHolder();
				holder.name = (TextView) convertView.findViewById(R.id.import_file_name);
				holder.row = (RelativeLayout) convertView.findViewById(R.id.import_app_row);
				holder.checkbox = (CheckBox) convertView.findViewById(R.id.import_file_checkbox);
				convertView.setTag(holder);

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

			final String fileName = getItem(position);
			holder.name.setText(StatsCsvReaderWriter.getPackageName(fileName));

			holder.checkbox.setChecked(importFilenames.contains(fileName));

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

				@Override
				public void onClick(View v) {

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

					if (checkbox.isChecked()) {
						importFilenames.add(fileName);
					} else {
						importFilenames.remove(fileName);
					}
				}
			});

			holder.checkbox.setTag(fileName);

			holder.checkbox.setOnClickListener(new CheckBox.OnClickListener() {

				@Override
				public void onClick(View v) {
					boolean isChecked = ((CheckBox) v).isChecked();
					if (isChecked) {
						importFilenames.add(fileName);
					} else {
						importFilenames.remove(fileName);
					}

				}
			});

			return convertView;
		}

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

}
