package edu.hm.cs.vss.remote;

import edu.hm.cs.vss.*;
import edu.hm.cs.vss.log.Logger;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Observable;
import java.util.stream.Stream;

/**
 * Created by Fabio Hellmann on 14.04.2016.
 */
public class RemoteTable extends Observable implements Table, Philosopher.OnStandUpListener {
    private final String host;
    private final Logger logger;
    private final RmiTable table;
    private final BackupService backupService;

    public RemoteTable(final String host, Logger logger) throws Exception {
        this.host = host;
        this.logger = logger;
        this.backupService = BackupService.create(this);
        final Registry registry = LocateRegistry.getRegistry(host, NETWORK_PORT);
        table = (RmiTable) registry.lookup(Table.class.getSimpleName());
    }

    @Override
    public String getName() {
        return host;
    }

    @Override
    public void connectToTable(final String tableHost) {
        try {
            logger.log("Requesting the remote table " + host + " to add the table " + tableHost);
            table.addTable(tableHost);
        } catch (RemoteException e) {
            handleRemoteTableDisconnected(e);
        }
    }

    @Override
    public void disconnectFromTable(final String tableHost) {
        try {
            logger.log("Requesting the remote table " + host + " to delete the table " + tableHost);
            table.removeTable(tableHost);
        } catch (RemoteException e) {
            handleRemoteTableDisconnected(e);
        }
    }

    @Override
    public Stream<Table> getTables() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void addPhilosopher(Philosopher philosopher) {
        try {
            table.addPhilosopher(getName(), philosopher.getName(), philosopher.isHungry());
        } catch (RemoteException e) {
            handleRemoteTableDisconnected(e);
        }
    }

    @Override
    public void removePhilosopher(Philosopher philosopher) {
        try {
            table.removePhilosopher(getName(), philosopher.getName());
        } catch (RemoteException e) {
            handleRemoteTableDisconnected(e);
        }
    }

    @Override
    public Stream<Philosopher> getPhilosophers() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void addChair(Chair chair) {
        try {
            table.addChair(getName(), chair.toString());
        } catch (RemoteException e) {
            handleRemoteTableDisconnected(e);
        }
    }

    @Override
    public void removeChair(Chair chair) {
        try {
            table.removeChair(getName(), chair.toString());
        } catch (RemoteException e) {
            handleRemoteTableDisconnected(e);
        }
    }

    @Override
    public Stream<Chair> getChairs() {
        return backupService.getChairs();
    }

    @Override
    public Chair getNeighbourChair(Chair chair) {
        throw new UnsupportedOperationException();
    }

    @Override
    public TableMaster getTableMaster() {
        return mealCount -> mealCount <= getBackupService().getPhilosophers()
                .mapToInt(Philosopher::getMealCount).min().orElse(0) + TableMaster.MAX_DEVIATION;
    }

    @Override
    public BackupService getBackupService() {
        return backupService;
    }

    @Override
    public void setTableMaster(TableMaster tableMaster) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void onStandUp(Philosopher philosopher) {
        try {
            table.onStandUp(getName(), philosopher.getName());
        } catch (RemoteException e) {
            handleRemoteTableDisconnected(e);
        }
    }

    protected RmiTable getRmi() {
        return table;
    }

    protected void handleRemoteTableDisconnected(final RemoteException e) {
        //logger.log(e.getMessage());
        // e.printStackTrace();
        setChanged();
        notifyObservers(RemoteTable.this);
    }
}

@@ -82,16 +82,83 @@
 ogger;%0A%0A
+import java.net.InetAddress;%0Aimport java.net.UnknownHostException;%0A
 import j
@@ -174,32 +174,32 @@
 emoteException;%0A
-
 import java.rmi.
@@ -1917,36 +1917,41 @@
 dPhilosopher(get
-Name
+LocalHost
 (), philosopher.
@@ -2211,28 +2211,33 @@
 losopher(get
-Name
+LocalHost
 (), philosop
@@ -2566,36 +2566,41 @@
 ble.addChair(get
-Name
+LocalHost
 (), chair.toStri
@@ -2807,28 +2807,33 @@
 oveChair(get
-Name
+LocalHost
 (), chair.to
@@ -3746,20 +3746,25 @@
 ndUp(get
-Name
+LocalHost
 (), phil
@@ -4111,24 +4111,24 @@
 tChanged();%0A
-
         noti
@@ -4163,11 +4163,326 @@
 );%0A    %7D
+%0A%0A    private String getLocalHost() %7B%0A        try %7B%0A            return InetAddress.getLocalHost().getHostAddress();%0A        %7D catch (UnknownHostException e) %7B%0A            e.printStackTrace();%0A            return %22127.0.0.1%22; // TODO This is a potential bug if the host can not be detected automaticly%0A        %7D%0A    %7D
 %0A%7D%0A

Replace remote name with local name