package io.coinswap.client;

import com.google.bitcoin.kits.WalletAppKit;
import com.google.common.util.concurrent.MoreExecutors;
import io.coinswap.Coins;
import io.coinswap.net.Connection;
import io.coinswap.swap.AtomicSwap;
import io.coinswap.swap.AtomicSwapClient;
import io.coinswap.swap.AtomicSwapTrade;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.text.Font;
import javafx.scene.text.FontSmoothingType;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.scene.image.Image;
import net.minidev.json.JSONObject;
import netscape.javascript.JSObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.File;
import java.io.FileInputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class Main extends Application {
    private static final Logger log = LoggerFactory.getLogger(Main.class);

    public static final String APP_NAME = "Coinswap";
    public static final String APP_VERSION = "0.0.1-SNAPSHOT";

    public static final File dataDir = new File("./data");

    private static final int MIN_WIDTH = 740;
    private static final int MIN_HEIGHT = 400;
    private static final int DEFAULT_WIDTH = 800;
    private static final int DEFAULT_HEIGHT = 720;

    private ClientUI ui;
    private Controller controller;
    private ArrayList<Coin> coins;
    private Map<String, CoinModel> models;

    @Override
    public void start(Stage mainWindow) {
        ui = new ClientUI();
        ui.engine.getLoadWorker().stateProperty().addListener((ov, oldState, state) -> {
            controller = new Controller(ui.engine);
            coins = Coins.get(dataDir);
            models = new HashMap<String, CoinModel>();

            // for each Coin, create JS-side model and insert into JS-side collection
            JSObject coinCollection = (JSObject) controller.app.get("coins");
            for(Coin coin : coins) {
                coin.getSetupFuture().addListener(new Runnable() {
                    @Override
                    public void run() {
                        CoinModel model = new CoinModel(controller, coin);
                        models.put(coin.id, model);
                        coinCollection.call("add", new Object[]{ model.object });
                    }
                }, controller.e);

                coin.start();
            }

            mainWindow.setTitle(APP_NAME);
            mainWindow.setScene(new Scene(ui, DEFAULT_WIDTH, DEFAULT_HEIGHT));
            mainWindow.setMinWidth(MIN_WIDTH);
            mainWindow.setMinHeight(MIN_HEIGHT);

            mainWindow.getIcons().add(new Image(getClass().getResourceAsStream("/images/icon128.png")));
            mainWindow.getIcons().add(new Image(getClass().getResourceAsStream("/images/icon64.png")));
            mainWindow.getIcons().add(new Image(getClass().getResourceAsStream("/images/icon32.png")));

            mainWindow.show();
        });
    }

    @Override
    public void stop() throws Exception {
        super.stop();
        for(Coin coin : coins) coin.stop();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

class ClientUI extends Region {
    WebView browser;
    WebEngine engine;

    public ClientUI() {
        Platform.setImplicitExit(true);

        browser =  new WebView();
        engine = browser.getEngine();

        browser.setContextMenuEnabled(false);
        getStyleClass().add("browser");
        engine.load(getClass().getResource("/index.html").toExternalForm());
        engine.setUserStyleSheetLocation(getClass().getResource("/css/browser.css").toExternalForm());
        browser.setFontSmoothingType(FontSmoothingType.GRAY);

        // load fonts
        // TODO: put this somewhere else
        Font.loadFont(getClass().getResource("/fonts/lato-regular.woff").toExternalForm(), 10);
        Font.loadFont(getClass().getResource("/fonts/lato-bold.woff").toExternalForm(), 10);
        Font.loadFont(getClass().getResource("/fonts/lato-black.woff").toExternalForm(), 10);
        Font.loadFont(getClass().getResource("/fonts/lato-italic.woff").toExternalForm(), 10);
        Font.loadFont(getClass().getResource("/fonts/fontawesome-webfont.eot").toExternalForm(), 10);

        getChildren().add(browser);
    }

    private Node createSpacer() {
        Region spacer = new Region();
        HBox.setHgrow(spacer, Priority.ALWAYS);
        return spacer;
    }

    @Override
    protected void layoutChildren() {
        double w = getWidth();
        double h = getHeight();
        layoutInArea(browser, 0, 0, w, h, 0, HPos.CENTER, VPos.CENTER);
    }
}
@@ -378,16 +378,50 @@
 atform;%0A
+import javafx.event.EventHandler;%0A
 import j
@@ -827,24 +827,57 @@
 mage.Image;%0A
+import javafx.stage.WindowEvent;%0A
 import net.m
@@ -3417,24 +3417,374 @@
 %0A        %7D);
+%0A%0A        mainWindow.setOnCloseRequest(new EventHandler%3CWindowEvent%3E() %7B%0A            @Override%0A            public void handle(WindowEvent windowEvent) %7B%0A                try %7B%0A                    stop();%0A                %7D catch(Exception ex) %7B%0A                %7D finally %7B%0A                    System.exit(0);%0A                %7D%0A            %7D%0A        %7D);
 %0A    %7D%0A%0A    
@@ -3839,30 +3839,8 @@
 n %7B%0A
-        super.stop();%0A
     
@@ -3875,24 +3875,46 @@
 oin.stop();%0A
+        super.stop();%0A
     %7D%0A%0A    p

Stop threads on window close