package com.smack.demo;

import java.io.File;
import java.util.HashMap;
import java.util.Scanner;

import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.omemo.OmemoConfiguration;
import org.jivesoftware.smackx.omemo.OmemoFingerprint;
import org.jivesoftware.smackx.omemo.OmemoManager;
import org.jivesoftware.smackx.omemo.OmemoService;
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
import org.jivesoftware.smackx.omemo.exceptions.UndecidedOmemoIdentityException;
import org.jivesoftware.smackx.omemo.internal.CipherAndAuthTag;
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
import org.jivesoftware.smackx.omemo.internal.OmemoMessageInformation;
import org.jivesoftware.smackx.omemo.listener.OmemoMessageListener;
import org.jivesoftware.smackx.omemo.signal.SignalOmemoService;
import org.jivesoftware.smackx.omemo.util.OmemoKeyUtil;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.whispersystems.libsignal.IdentityKey;

public class E2E {

	private static OmemoManager omemoManager;

	public static void main(String[] args) {

		try {

			Scanner sc = new Scanner(System.in);
			try {

				System.out.println("enter username");
				String username = sc.nextLine();

				System.out.println("enter password");
				String password = sc.nextLine();

				try {

					SignalOmemoService.acknowledgeLicense();
					SignalOmemoService.setup();

					XMPPConnection connection = GetXmppConnetion.getConnection(username, password);

					System.out.println("path ");
					String path = sc.nextLine();

					OmemoConfiguration.setFileBasedOmemoStoreDefaultPath(new File(path));
					omemoManager = OmemoManager.getInstanceFor(connection);
					omemoManager.addOmemoMessageListener(new OmemoMessageListener() {

						@Override
						public void onOmemoKeyTransportReceived(CipherAndAuthTag arg0, Message arg1, Message arg2,
								OmemoMessageInformation arg3) {
							System.out.println("received something ");

						}

						@Override
						public void onOmemoMessageReceived(String decryptedBody, Message encryptedMessage,
								Message wrappingMessage, OmemoMessageInformation omemoInformation) {
							System.out.println("decrypted message :- " + decryptedBody);
							// Get identityKey of sender
							IdentityKey senderKey = (IdentityKey) omemoInformation.getSenderIdentityKey()
									.getIdentityKey();
							OmemoService<?, IdentityKey, ?, ?, ?, ?, ?, ?, ?> service = (OmemoService<?, IdentityKey, ?, ?, ?, ?, ?, ?, ?>) OmemoService
									.getInstance();

							// get the fingerprint of the key
							OmemoFingerprint fingerprint = service.getOmemoStoreBackend().keyUtil()
									.getFingerprint(senderKey);
							// Lookup trust status
							boolean trusted = omemoManager.isTrustedOmemoIdentity(omemoInformation.getSenderDevice(),
									fingerprint);

							System.out.println("(O) " + (trusted ? "T" : "D") + " " + encryptedMessage.getFrom() + ": "
									+ decryptedBody);

						}
					});
					omemoManager.initialize();

					String line1 = "";

					while (!line1.equals("stop")) {

						Message encrypted = null;

						System.out.println("enter to address ");
						String to = sc.nextLine();

						System.out.println("message :- ");
						String message = sc.nextLine();

						String cases = sc.nextLine();

						EntityBareJid recipientJid = JidCreate.entityBareFrom(to + "@" + GetXmppConnetion.strServer);
						String recipient = to;

						switch (cases) {
						case "Omemo":

							try {
								encrypted = OmemoManager.getInstanceFor(connection).encrypt(recipientJid,
										message.toString());
								System.out.println("encrupted " + encrypted.toXML());
							}
							// In case of undecided devices
							catch (UndecidedOmemoIdentityException e) {
								System.out.println("Undecided Identities: ");
								for (OmemoDevice device : e.getUndecidedDevices()) {
									System.out.println(device);
								}
							}
							// In case we cannot establish session with some
							// devices
							catch (CannotEstablishOmemoSessionException e) {
								encrypted = omemoManager.encryptForExistingSessions(e, message.toString());
							}

							// send
							if (encrypted != null) {
								ChatManager.getInstanceFor(connection).chatWith(recipientJid).send(encrypted);
							}
							break;

						case "trust":

							HashMap<OmemoDevice, OmemoFingerprint> fingerprints = omemoManager
									.getActiveFingerprints(recipientJid);

							// Let user decide
							for (OmemoDevice d : fingerprints.keySet()) {
								System.out.println("Trust (1), or distrust (2)?");
								System.out.println(OmemoKeyUtil.prettyFingerprint(fingerprints.get(d)));
								int decision = Integer.parseInt(sc.nextLine());
								if (decision == 1) {
									omemoManager.trustOmemoIdentity(d, fingerprints.get(d));
								} else {
									omemoManager.distrustOmemoIdentity(d, fingerprints.get(d));
								}
							}
							break;
						}

						// encrypt

					}

				} catch (Exception e) {
					e.printStackTrace();
				}

			} catch (Exception e) {
				e.printStackTrace();
			}
		} catch (

		Exception e) {
			e.printStackTrace();
		}

	}

}
