package hh.dejsem;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ScrollView;
import android.widget.TextView;

import java.io.File;

import hh.dejsem.clipboard.Clipboard;
import hh.dejsem.clipboard.HistFrag;
import hh.dejsem.fm.FragFMPeer;
import hh.dejsem.fm.FragFMServer;
import hh.dejsem.hack.HackA;
import hh.dejsem.net.NetInfoFrag;
import hh.lib.D;

/**
 * ● main Activity, GUI rozcestník všech funkcí:
 * <ol>
 *     <li>sdílení clipboardu skrze server včetně udržování historie</li>
 *     <li>sdílení datových souborů se serverem</li>
 *     <li>peer-to-peer přenos datových souborů v LANu</li>
 *     <li>vystavení datových souborů na serveru</li>
 *     <li>informace o síťovém připojení včetně průchodnosti internetové last mile</li>
 * </ol>
 * ● síťové přenosy jsou šifrovány skrze SSL s asymetrickými klíči
 * ● vyhrazeno je 10 oddělených přenosových kanálů s různými klíči, přičemž kanál 0 se nešifruje
 * ● pro každý kanál je vyhrazeno 10 TCP-portů
 * ● TCP-port 0 je vyhrazen pro zadávání příkazů serveru
 * ● TCP-porty 1-9 slouží pro paralelní asynchronní datové přenosy
 * ● porty se alokují relativně k portu 17000 na portech 17000-17099
 * ● struktura čísla portu je 170XY, X = číslo šifrovaného kanálu, Y = číslo paralelního přenosu v kanálu
 */

public class Main
		extends Act
		implements
			Handler.Callback,
			GetReady.ReadyListener,
			HistFrag.Listener {

	static final String TITLETEXT = "main";

	/**
	 * helper pro log eye-catcher pro debug-verzi aplikace; volá se z top-level-aktivit.
	 *
	 * @param d
	 * @param act caller activity
	 */
	static public void eyeCatcher(D d, Context act) {
		if(act.getClass().getPackage().getName().startsWith("hh.dej" + "D")) {   // +++
			K.UDP_PORT = 4224;
			d.l(String.format("========= %s, %s, logLevel=%d, hashCode=%x =========",
					act.getResources().getString(R.string.app_name),
					act.getClass().getSimpleName(),
					d.getLogLevel(),
					act.hashCode()
			));
		}
	}

	TextView clipboardContent;
	ScrollView clipboardScroll;
	View.OnLongClickListener clickPush, clickPull;
	View.OnClickListener clickHist, clickMenu, clickSrv, clickPeer, clickNet;
	View bPush, bPull, bHist, bMenu, bFiles, bPeer, bNet;
	Clipboard clipboard;

	@Override
	public void onCreate(Bundle b) {
		super.onCreate(b);
		eyeCatcher(d, this);

		setContentView(R.layout.basic_layout);
		TitleBar.assign(this, R.id.title_bar, TITLETEXT);
		if(GetReady.isReady(d)) setup();
		else {
			GetReady.getReady(d, this);
			TextView tv = new TextView(this);
			tv.setText("waiting for password & SD card permissions");
			((ViewGroup) findViewById(R.id.panel)).addView(tv);
		}
	}

	@Override
	public void onStart() {
		super.onStart();
		if(K.title != null) K.title.reassign(this, R.id.title_bar);
	}

	@Override
	public void onResume() {
		super.onResume();
		refreshTv();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
//		K.histlist = null;
		K.cmdConnClose(d);
		final Fragment df = d.getFmgr().findFragmentByTag("word");
		if(df != null) ((DialogFragment)df).dismiss();
	}

	@Override
	public void onBackPressed() {
		if(d.ll(4)) d.l(String.format("onBackPressed, BackStackSize=%d", getFragmentManager().getBackStackEntryCount()));
		refreshTv();
		super.onBackPressed();
	}

	@Override
	public void onReady(boolean success) {
		if(success) setup();
		else finish();
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if(d.ll(4)) d.l(String.format("onActivityResult: requestCode=%d, resultCode=%d", requestCode, resultCode));

		if(requestCode == K.GETPW) {
			if(K.word == null || K.word.equals("") || K.word.equals("BAD") || resultCode != RESULT_OK) finish();
			else if(resultCode == RESULT_OK) K.sdUri.getSdUri();
		}
		else if(resultCode == RESULT_OK) {
			if(requestCode == K.HISTORY) clipboard.pull(data.getStringExtra("ENTRYNAME"));
			else if(requestCode == K.CHOOSE_SD_CARD_TREE) K.sdUri.saveUriPermissions(data);
		}
	}

	@Override
	public void getHistEntry(String entry) {
		clipboard.pull(entry);
		refreshTv();
	}

	void setup() {
		if(K.cacheFileR == null) K.cacheFileR = new File(getCacheDir(), K.CACHEFNR_KEY);

		((ViewGroup)findViewById(R.id.panel)).addView(getLayoutInflater().inflate(R.layout.main_panel, null));

		bPush = findViewById(R.id.bPush);
		bPull = findViewById(R.id.bPull);
		bHist = findViewById(R.id.bHist);
		bMenu = findViewById(R.id.bMenu);
		bFiles = findViewById(R.id.bFiles);
		bPeer = findViewById(R.id.bPeer);
		bNet = findViewById(R.id.bNet);

		clickPush = new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { return push(); } };
		clickPull = new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { return pull(); } };
		clickHist = new View.OnClickListener() { @Override public void onClick(View v) { history(); } };
		clickMenu = new View.OnClickListener() { @Override public void onClick(View v) { handleContextMenu(); } };
		clickSrv = new View.OnClickListener() { @Override public void onClick(View v) { server(); } };
		clickPeer = new View.OnClickListener() { @Override public void onClick(View v) { peer(); } };
		clickNet = new View.OnClickListener() { @Override public void onClick(View v) { netinfo(); } };

		clipboardContent = (TextView)findViewById(R.id.cbText);
		clipboardScroll = (ScrollView)findViewById(R.id.cbScroll);
		registerForContextMenu(bMenu);
		bPush.setOnLongClickListener(clickPush);
		bPull.setOnLongClickListener(clickPull);
		bHist.setOnClickListener(clickHist);
		bMenu.setOnClickListener(clickMenu);
		bFiles.setOnClickListener(clickSrv);
		bPeer.setOnClickListener(clickPeer);
		bNet.setOnClickListener(clickNet);
		clipboard = new Clipboard(this, this, d);

		refreshTv();
	}

	void handleContextMenu() {
		d.l(4, "openContextMenu");
		openContextMenu(bMenu);
	}

	void refreshTv() {
		if(clipboard != null) {
			clipboardContent.setText(clipboard.getCB());
			clipboardContent.invalidate();
		}
		if(K.title != null) K.title.setText(TITLETEXT).update();
	}

	boolean push() {    // push clipboard to server
		if(d.ll(4)) d.l("push to shared clipboard CLICKED");
		return clipboard.push();
	}

	boolean pull() {    // pull last clipboard entry from server
		if(d.ll(4)) d.l("pull from shared clipboard CLICKED");
		if(clipboard.pull()) {
			refreshTv();
			return true;
		}
		else return false;
	}

	void history() {    // clipboard history
		if(d.ll(4)) d.l("history CLICKED");
		HistFrag history = (HistFrag)getSupportFragmentManager().findFragmentByTag(K.HISTORY_TAG);
		if(history == null) history = HistFrag.instantiate(d/*, this*/);
//		HistFrag history = HistFrag.instantiate(d/*, this*/);
		attachFragment(history, R.id.panel, K.HISTORY_TAG);
	}

	void netinfo() {
		if(d.ll(4)) d.l("netinfo CLICKED");
		NetInfoFrag netInfo = (NetInfoFrag)getSupportFragmentManager().findFragmentByTag(K.NET_INFO_TAG);
		if (netInfo == null) netInfo = NetInfoFrag.instantiate(d);
		attachFragment(netInfo, R.id.panel, K.NET_INFO_TAG);
	}

	void server() {
		FragFMServer fmSrv = (FragFMServer)getSupportFragmentManager().findFragmentByTag(K.FM_SRV_TAG);
		if (fmSrv == null) fmSrv = FragFMServer.instantiate(d);
		attachFragment(fmSrv, R.id.panel, K.FM_SRV_TAG);
	}

	void peer() {
		FragFMPeer fmPeer = (FragFMPeer)getSupportFragmentManager().findFragmentByTag(K.FM_PEER_TAG);
		if (fmPeer == null) fmPeer = FragFMPeer.instantiate(d);
		attachFragment(fmPeer, R.id.panel, K.FM_PEER_TAG);
	}

	void attachFragment(Fragment fragment, int container, String tag) {
		d.l("+++ attachFragment, fragment=" + fragment);
		getSupportFragmentManager()
				.beginTransaction()
				.replace(container, fragment, tag)
				.addToBackStack(null)
				.commitAllowingStateLoss();
	}

	@Override
	public void hack() {
		startActivity(new Intent(this, HackA.class));
	}
}
