
public abstract class Observer {

	String servIp;
	int servPort;
	int selfPort;
	int print_times = 0;
   PrintFactory PF;
   Strategy print_method;

	Observer(String serv_ip, int serv_port, int self_port, PrintFactory factory) {
		servIp = serv_ip;
		servPort = serv_port;
		selfPort = self_port;
      PF = factory;
	}
		
	void dispose() {
		
		ClientNetProxy prox = new ClientNetProxy(servIp, servPort);
		prox.sendMessage( Integer.toString(selfPort) + " Unregister");
		prox.dispose();
		
	}
	
	public void run() {
		
		boolean isconnected = false;
		
		while ( ! isconnected ) {
			ClientNetProxy prox = new ClientNetProxy(servIp, servPort);
			prox.sendMessage( Integer.toString(selfPort) + " Register" );

			String mess = prox.getMessage();
			if(mess.equals("DONE")) {
				isconnected = true;
				System.out.println("connected to the server!");
				break;
			}
		}

		ServerNetProxy serv = new ServerNetProxy(selfPort);
		
		while( true ) {
			
			serv.accept();
			
			String mess = serv.getMessage();
			
			int state = Integer.parseInt(mess);
			
			handle(state);
			
			serv.dispose();
			
		}
	
	}
	
	public abstract void handle(int number);
	
}



class ObserverFirst extends Observer
{
	int old_state = -1;
		ObserverFirst(String serv_ip, int serv_port, int self_port, PrintFactory factory) {
		super(serv_ip, serv_port, self_port,factory);
      print_method = PF.getStrategy();
	}
	
	
	public void handle(int number) {
		
		//if(number != old_state)
			//System.out.println("[Observer 1]: state changed from " + 
						//Integer.toString(old_state) + " to " + Integer.toString(number));
      if(print_times % 3 == 0)
      {
         print_method = PF.getStrategy();
      }
            
		if(number != old_state)
		{
         print_times+=1;
         print_method.print(number);
      }
		old_state = number;
	}
	
}


class ObserverSecond extends Observer
{
	
	ObserverSecond(String serv_ip, int serv_port, int self_port, PrintFactory factory) {
		super(serv_ip, serv_port, self_port,factory);
      print_method = PF.getStrategy();
	}
	
	private boolean isPrime(int n) {
		
		// deal with special cases
		if(n == 1)
			return false;
		if(n == 2)
			return true;
		
	    //check if n is a multiple of 2
	    if (n%2==0) return false;
	    //if not, then just check the odds
	    for(int i=3;i*i<=n;i+=2) {
	        if(n%i==0)
	            return false;
	    }
	    
	    return true;
	}
	
	
	public void handle(int number) {
		if(print_times % 3 == 0)
      {
         print_method = PF.getStrategy();
      }

		if(isPrime(number)) 
         print_method.print(number);
         print_times+=1;
			//System.out.println("[Observer 2]: prime detected " + Integer.toString(number));
		
	}
	
}


class ObserverThird extends Observer
{
	int count = 0;
	int old_state = -1;
	
	ObserverThird(String serv_ip, int serv_port, int self_port, PrintFactory factory) {
		super(serv_ip, serv_port, self_port,factory);
       print_method = PF.getStrategy();
	}

	
	public void handle(int number) {
      if(print_times % 3 == 0)
      {
         print_method = PF.getStrategy();
      }

		if(number != old_state) {
			++ count;
			old_state = number;
		}
		
		if ( count % 4 == 0 ) {
         print_times+=1;
         print_method.print(number);
			//System.out.println("[Observer 3] every 4th state changed!");
			count = 0;
		}
		
	}	
	
}


