package OAuth_AuthCodeMode_Simplified2;

import Scheduler.Process;
import Scheduler.Scheduler;

public class OAuth_Simplified2 {

	public static void main(String[] args) {

		Client c = new Client();
		ResourceOwner ro =  new ResourceOwner();
		AuthorizationServer as = new AuthorizationServer();
		ResourceServer rs = new ResourceServer();

		Process[] arr = {ro, c, as, rs};
		Scheduler S = new Scheduler(arr, false);
	    long startTime = System.currentTimeMillis();
		S.start();
		Runtime.getRuntime().addShutdownHook(new Thread()
	    {
	      public void run()
	      {
	    	    long endTime = System.currentTimeMillis();
	    	    long duration = (endTime - startTime);  //Total execution time in milli seconds
	    	    System.out.println("Started in ms: "+ startTime);
	    	    System.out.println("Ended in ms  : "+ endTime);
	    	    System.out.println("Duration in ms: "+ duration);


	      }
	    });


	}
}

//-------------------------ResourceServer ----------------------------------

class ResourceServer extends Process {

	String state;

	public void run() {

		for (int i = 0; i < 10; i++) {
			System.out.println("RS: "+ i);
			// try {Thread.sleep(100);} catch (Exception e){}
			state = "Start";//--
			System.out.println("RS : "+state);

			//receive("C-->RS: Resource_Requested_With_AccessToken","Request_Failed"); //19
			//if (chosen.equals("C-->RS: Resource_Requested_With_AccessToken")) {
			receive("Resource_Requested_With_AccessToken"); //19
				state = "Resource_Requested_With_AccessToken";
				System.out.println("RS : "+state);

				send("Protected_Resource_Sent","InvalidAccessToken");
				if (chosen.equals("Protected_Resource_Sent")) {
					state = "Protected_Resource_Sent"; //20
					System.out.println("RS : "+state);
				}
				else {
					state = "InvalidAccessToken"; //21
					System.out.println("RS : "+state);
				}
			//}
			//else requestFailed(); //18 End if C-->RS: Resource_Requested_With_AccessToken

		}//End for
	}//End run()

//	public void requestFailed() {
//		state = "Request_Failed";
//		System.out.println("RS : "+state);
//	}
//
} //End ResourceServer class


class AuthorizationServer extends Process  {

	String state;

	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println("AS: "+ i);

			 //try {Thread.sleep(100);} 	catch (Exception e){}
			state = "Start";//--
			System.out.println("AS : "+state);

//			receive("RO-->AS: Authr_Service_Requested_For_Client","Request_Failed"); //5
//			if(chosen.equals("RO-->AS: Authr_Service_Requested_For_Client")) {
			receive("Authr_Service_Requested_For_Client"); //5
				state = "Authr_Service_Request_For_Client_Rcvd";//--
				System.out.println("AS : "+state);

//				send("AS-->RO: CV_RO_Authentication_Requested","Request_Failed"); //6
//				if(chosen.equals("AS-->RO: CV_RO_Authentication_Requested")) {
				send("RO_Authentication_Requested"); //6
					state = "RO_Authentication_Requested";
					System.out.println("AS : "+state);

//					receive("RO-->AS: RO_Credentials_Entered","Request_Failed"); //7
//					if(chosen.equals("RO-->AS: RO_Credentials_Entered")) {
					receive("RO_Credentials_Obtained"); //7
						state = "RO_Credentials_Rcvd";
						System.out.println("AS : "+state);

//						send("AS-->RO: ROA_RO_Authr_Requested","Request_Failed"); //8
//						if(chosen.equals("AS-->RO: ROA_RO_Authr_Requested")) {
						send("ROA_RO_Authr_Requested","RO_Authentication_Failed"); //8
						if(chosen.equals("ROA_RO_Authr_Requested")) {
							state = "ROA_RO_Authr_Requested";
							System.out.println("AS : "+state);

							receive("Authorization_Granted","Authorization_Denied"); //9
							if(chosen.equals("Authorization_Granted")) {
								state = "Authorization_Granted";
								System.out.println("AS : "+state);

//								send("AS-->C: RO_Redirected_With_AuthCode","Request_Failed"); //10
//								if(chosen.equals("AS-->C: RO_Redirected_With_AuthCode")) {
								send("RO_Redirected_With_AuthCode"); //10
									state = "RO_Redirected_With_AuthCode";
									System.out.println("AS : "+state);

//									receive("C-->AS: AccessToken_Requested_With_AuthCode_Redirect_URI","Request_Failed");//11
//									if(chosen.equals("C-->AS: AccessToken_Requested_With_AuthCode_Redirect_URI")) {
									receive("AccessToken_Requested_With_AuthCode_Redirect_URI");
										state = "AccessToken_Received_With_AuthCode_Redirect_URI";
										System.out.println("AS : "+state);

//										send("AS-->C: Client_Authentication_Requested","Request_Failed"); //12
//										if(chosen.equals("AS-->C: Client_Authentication_Requested")) {
										send("Client_Authentication_Requested");
											state = "Client_Authentication_Requested";
											System.out.println("AS : "+state);

//											receive("C-->AS: Client_Credentials_Sent","Request_Failed");//13
//											if(chosen.equals("C-->AS: Client_Credentials_Sent")) {
											receive("Client_Credentials_Sent");
												state = "Client_Credentials";
												System.out.println("AS : "+state);

												send("Client_Authenticated","Client_Authentication_Failed"); //14 ======check =========
												if(chosen.equals("Client_Authenticated")) {

													state = "Client_Authenticated";
													System.out.println("AS : "+state);

//													send("AS-->C: Validating_AuthCode_Redirect_URI","AS-->C: Validating_Refresh_Token");
//													if(chosen.equals("AS-->C: Validating_AuthCode_Redirect_URI")) {
													send("Validating_AuthCode_Redirect_URI"); //15
														state = "Validating_AuthCode_Redirect_URI"; //15
														System.out.println("AS : "+state);

														send("Access_Refresh_Token_Sent","Invalid_AuthCode");
														if(chosen.equals("Access_Refresh_Token_Sent")) {
															state = "Access_Refresh_Token_Sent";//17
															System.out.println("AS : "+state);
															waitForTokenRefreshRequest();
														}
														else {
															state = "Invalid_AuthCode";
															System.out.println("AS : "+state);
															requestFailed(); // 17 End if AS-->C: Access_Refresh_Token_Sent
													}
//													else { //AS-->C: Validating_Refresh_Token  //15
//														state = "AS-->C: Validating_Refresh_Token"; //16
//														System.out.println("AS : "+state);
//
//														send("AS-->C: Access_Refresh_Token_Sent","Invalid_RefreshToken");
//														if(chosen.equals("AS-->C: Access_Refresh_Token_Sent")) {
//															state = "AS-->C: Access_Refresh_Token_Sent";//17
//															System.out.println("AS : "+state);
//															waitForTokenRefreshRequest();
//														}
//														else {
//															state = "Invalid_RefreshToken"; //18
//															System.out.println("AS : "+state);
//															requestFailed(); // 17 End if AS-->C: Access_Refresh_Token_Sent
//														}
//													} //end else AS-->C: Validating_Refresh_Token  //15

												}
												else { //14 AS-->C: Client_Authentication_Failed
													state="Client_Authentication_Failed";
													System.out.println("AS : "+state);
													requestFailed();
												}

//											} else requestFailed(); //13 - C-->AS: Client_Credentials_Sent
//										} else requestFailed(); //12 - AS-->C: Client_Authentication_Requested
//									}  else requestFailed(); //11 - C-->AS: AccessToken_Requested_With_AuthCode_Redirect_URI
//								} else requestFailed(); //10 -  AS-->C: RO_Redirected_With_AuthCode
							}
							else
							{ // 9 -  RO-->AS: Authorization_Granted / Denied
								state = "Authorization_Denied";
								send("Request_Failed");
								System.out.println("AS : "+state);
								requestFailed();
							}
						}  else { //8 - AS-->RO: ROA_RO_Authr_Requested , RO_Authentication_Failed
							send("Request_Failed");
							state="RO_Authentication_Failed";
							System.out.println("AS : "+state);
							requestFailed();
						}
//					} else requestFailed(); //7 - RO-->AS: RO_Credentials_Entered
//				} else requestFailed(); //6 - AS-->RO: RO_Authentication_Requested
//			} else requestFailed(); //5 - End if RO-->AS: Auth_Service_Requested_For_Client
		} //End for
		System.exit(0);
	} // End run()

	public void waitForTokenRefreshRequest() {
		receive("AccessToken_Requested_With_RefreshToken","AS_Request_Completed"); //22
		if(chosen.equals("AccessToken_Requested_With_RefreshToken")) {
			state = "AccessToken_Requested_With_RefreshToken";
			System.out.println("AS : "+state);
			send("New_AccessToken"," Invalid_RefreshToken");
			if(chosen.equals("New_AccessToken")) {
				state = "New_AccessToken_RefreshToken"; //Final
				System.out.println("AS : "+state);
				waitForTokenRefreshRequest();
			}
			else {
				requestFailed();
			}


		}
		else {
			state = "Success";
			System.out.println("AS : "+state);
		}
	}
	public void requestFailed() {
		state = "Request_Failed";
		System.out.println("AS : "+state);
	}
}//End AuthorizationServer class

class ResourceOwner extends Process {
	String state;

	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println("RO: "+ i);

			// try {Thread.sleep(100);} catch (Exception e){}
			state = "Start";
			System.out.println("RO : "+state);

			send("Service_Requested");//1
			//send("RO-->C: Service_Requested","Request_Failed");//1
			//if (chosen.equals("RO-->C: Service_Requested")) {
				state = "Service_Requested";
				System.out.println("RO : "+state);

//				receive("C-->RO: Sup_Authr_Servers_Listed", "Request_Failed"); //2
//				if (chosen.equals("C-->RO: Sup_Authr_Servers_Listed")) {

				 receive("Sup_Authr_Servers_List"); //2
					state = "Sup_Authr_Servers_Rcvd";
					System.out.println("RO : "+state);

//					send("RO-->C: Pref_Authr_Server_Selected","Request_Failed"); //3
//					if (chosen.equals("RO-->C: Pref_Authr_Server_Selected")) {
					send("Pref_Authr_Server_Selected"); //3
						state = "Pref_Authr_Server_Selected";
						System.out.println("RO : "+state);

//						receive("C-->RO: Redirected_to_Pref_Authr_Server", "Request_Failed");//4
//						if (chosen.equals("C-->RO: Redirected_to_Pref_Authr_Server")) {
						receive("Redirected_to_Pref_Authr_Server");//4
							state = "Redirected_to_Pref_Authr_Server";
							System.out.println("RO : "+state);

//							send("RO-->AS: Authr_Service_Requested_For_Client","Request_Failed"); //5
//							if(chosen.equals("RO-->AS: Authr_Service_Requested_For_Client")) {
							send("Authr_Service_Requested_For_Client"); //5
								state = "Authr_Service_Requested_For_Client";
								System.out.println("RO : "+state);

//								receive("AS-->RO: CV_RO_Authentication_Requested","Request_Failed"); //6
//								if(chosen.equals("AS-->RO: CV_RO_Authentication_Requested")) {
								receive("RO_Authentication_Requested");
									state = "RO_Authentication_Request_Rcvd";
									System.out.println("RO : "+state);

//									send("RO-->AS: RO_Credentials_Entered","Request_Failed"); //7
//									if(chosen.equals("RO-->AS: RO_Credentials_Entered")) {
									send("RO_Credentials_Obtained");//7
										state = "RO_Credentials";
										System.out.println("RO : "+state);

//										receive("AS-->RO: ROA_RO_Authr_Requested","Request_Failed"); //8
//										if(chosen.equals("AS-->RO: ROA_RO_Authr_Requested")) {
										receive("ROA_RO_Authr_Requested","RO_Authentication_Failed"); //8
										if(chosen.equals("ROA_RO_Authr_Requested")) {
											state = "ROA_RO_Authr_Request_Rcvd";
											System.out.println("RO : "+state);

											send("Authorization_Granted","Authorization_Denied"); //9
											if(chosen.equals("Authorization_Granted")) {
												state = "Authorization_Granted";
												System.out.println("RO : "+state);

												receive("Client_Service_Request_Completed","Client_Request_Failed");
												//receive("C-->RO: Service_Request_Completed","Request_Failed");
												if(chosen.equals("Client_Service_Request_Completed")) {
													state = "Success"; //Final
													System.out.println("RO : "+state);
												}
												else {
													state = "Request_Failed";
													System.out.println("RO : "+state);
													requestFailed();
												}
												/*receive("C-->RO: Service_Request_Completed","C-->RO: Request_Failed"); //21
												if(chosen.equals("C-->RO: Service_Request_Completed")){
													state = "Success"; //Final
													System.out.println("RO : "+state);
												}
												else {
													state = "Request_Failed";
													System.out.println("RO : "+state);
													requestFailed();
												}*/

											}
											else { // 9 -  RO-->AS: Authorization_Granted / Denied
												state = "Authorization_Denied";
												System.out.println("RO : "+state);
												requestFailed();
											}
										}
										else { //8 - AS-->RO: ROA_RO_Authr_Requested, AS-->RO: RO_Authentication_Failed
											state="RO_Authentication_Failed";
											System.out.println("RO : "+state);
											requestFailed();
										}
//									} else requestFailed(); //7 - RO-->AS: RO_Credentials_Entered
//								} else requestFailed(); //6 - AS-->RO: CV_RO_Authentication_Requested
//							} else requestFailed(); //5 - End if RO-->AS: Auth_Service_Requested_For_Client
//						} else requestFailed(); //4 - End if "C-->RO: Redirected_to_Pref_Authr_Server"
//					} else  requestFailed();  //3 - End if "RO-->C: Pref_Authr_Server_Selected"
//				} else requestFailed();   //2 - End if C-->RO: Sup_Authr_Servers_Listed
//			}   else requestFailed(); //1-  End if RO-->C: Service_Requested

		} //End for
		System.exit(0);
	} // End run()


	public void requestFailed() {
		state = "Request_Failed";
		System.out.println("RO : "+state);
	}

} // End ResourceOwner class


class Client extends Process {
	String state;
	boolean repeat = true;
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println("C: "+ i);


			state = "Start";
			System.out.println("C : "+state);
			//try {Thread.sleep(100);} catch (Exception e){}
			 receive("Service_Requested"); //1
			//receive("RO-->C: Service_Requested","Request_Failed"); //1
			//if (chosen.equals("RO-->C: Service_Requested")) {
				state = "Service_Request_Received";
				System.out.println("C : "+state);

//				send("C-->RO: Sup_Authr_Servers_Listed", "Request_Failed"); //2
//				if (chosen.equals("C-->RO: Sup_Authr_Servers_Listed")) {
				send("Sup_Authr_Servers_List");
					state = "Sup_Authr_Servers_Listed";
					System.out.println("C : "+state);

//					receive("RO-->C: Pref_Authr_Server_Selected","Request_Failed");//3
//					if(chosen.equals("RO-->C: Pref_Authr_Server_Selected")) {
					receive("Pref_Authr_Server_Selected");
						state = "Pref_Authr_Server_Selected";//--
						System.out.println("C : "+state);

//						send("C-->RO: Redirected_to_Pref_Authr_Server", "Request_Failed");//4
//						if(chosen.equals("C-->RO: Redirected_to_Pref_Authr_Server")) {
						send("Redirected_to_Pref_Authr_Server");
							state = "Redirected_to_Pref_Authr_Server";//--
							System.out.println("C : "+state);

							receive("RO_Redirected_With_AuthCode","Request_Failed"); //10
							if(chosen.equals("RO_Redirected_With_AuthCode")) {
//							receive("AS-->C: RO_Redirected_With_AuthCode");
								state = "RO_Redirected_With_AuthCode";
								System.out.println("C : "+state);

//								send("C-->AS: AccessToken_Requested_With_AuthCode_Redirect_URI","Request_Failed");//11
//								if(chosen.equals("C-->AS: AccessToken_Requested_With_AuthCode_Redirect_URI")) {
								send("AccessToken_Requested_With_AuthCode_Redirect_URI");
									state = "AccessToken_Requested_With_AuthCode_Redirect_URI";
									System.out.println("C : "+state);

//									receive("AS-->C: Client_Authentication_Requested","Request_Failed"); //12
//									if(chosen.equals("AS-->C: Client_Authentication_Requested")) {
									receive("Client_Authentication_Requested");
										state = "Client_Authentication_Request_Rcvd";
										System.out.println("C : "+state);

//										send("C-->AS: Client_Credentials_Sent","Request_Failed");//13
//										if(chosen.equals("C-->AS: Client_Credentials_Sent")) {
										send("Client_Credentials_Sent");
											state = "Client_Credentials_Sent";
											System.out.println("C : "+state);

											receive("Client_Authenticated","Client_Authentication_Failed"); //14  ======check =========
											if(chosen.equals("Client_Authenticated")) {
												state = "Client_Authenticated";
												System.out.println("C : "+state);

//												receive("AS-->C: Validating_AuthCode_Redirect_URI","AS-->C: Validating_Refresh_Token");
//												if(chosen.equals("AS-->C: Validating_AuthCode_Redirect_URI")) {
												receive("Validating_AuthCode_Redirect_URI");
													state = "Validating_AuthCode_Redirect_URI";//15
													System.out.println("C : "+state);

													receive("Access_Refresh_Token_Sent","Invalid_AuthCode");
													if(chosen.equals("Access_Refresh_Token_Sent")) {
														state = "Access_Refresh_Token_Rcvd";//17
														System.out.println("C : "+state);
														requestResource();
													}
													else {
														state="Invalid_AuthCode_Rcvd";
														System.out.println("C : "+state);
														send("Client_Request_Failed");
														//send("Request_Failed");
														requestFailed(); // 17 End if AS-->C: Invalid_AuthCode
												}
//												else { //AS-->C: Validating_Refresh_Token  //15
//													state = "AS-->C: Validating_Refresh_Token_Rcvd";  //16
//													System.out.println("C : "+state);
//
//													receive("AS-->C: Access_Refresh_Token_Sent","Invalid_RefreshToken");
//													if(chosen.equals("AS-->C: Access_Refresh_Token_Sent")) {
//														state = "AS-->C: Access_Refresh_Token_Rcvd"; //17
//														System.out.println("C : "+state);
//														requestResource();
//													}
//													else {
//														state = "Invalid_RefreshToken_Rcvd"; //18
//														System.out.println("C : "+state);
//														requestFailed();
//													}	// 18 End else
//												}
											}
											else {
												state = "Client_Authentication_Failed"; //14 AS-->C: Client_Authentication_Failed
												send("Client_Request_Failed");
												//send("Request_Failed");
												System.out.println("C : "+state);
												requestFailed(); //14 - AS-->C: Client_Authenticated
											}
//										} else requestFailed(); //13 - C-->AS: Client_Credentials_Sent
//									} else requestFailed(); //12 - AS-->C: Client_Authentication_Requested
//								} else requestFailed(); //11 - C-->AS: AccessToken_Requested_With_AuthCode_Redirect_URI
							}
							else requestFailed(); //10 -  AS-->C: RO_Redirected_With_AuthCode
//						} else requestFailed(); //4 - End if "C-->RO: Redirected_to_Pref_Authr_Server"
//					} else  requestFailed();  //3 - End if "RO-->C: Pref_Authr_Server_Selected"
//				}  else requestFailed();   //2 - End if C-->RO: Sup_Authr_Servers_Listed
//			}  else requestFailed(); //1-  End if RO-->C: Service_Requested
		} // End for
		System.exit(0);
	} // End run ()


    public void requestResource() {

    	//send("C-->RS: Resource_Requested_With_AccessToken","Request_Failed"); //19
		//if (chosen.equals("C-->RS: Resource_Requested_With_AccessToken")) {
    	send("Resource_Requested_With_AccessToken");
			state = "Resource_Requested_With_AccessToken";
			System.out.println("C : "+state);

			receive("Protected_Resource_Sent","InvalidAccessToken");
			if (chosen.equals("Protected_Resource_Sent")) {
				state = "Protected_Resource_Rcvd"; //20
				System.out.println("C : "+state);
//				if(repeat) {
//					requestResource();
//					repeat = false;
//				}
//				else {
				/*	send("C-->RO: Service_Request_Completed","C-->RO: Request_Failed"); //21
					if(chosen.equals("C-->RO: Service_Request_Completed")){*/
				send("Client_Service_Request_Completed");
				send("AS_Request_Completed");
				state = "Success"; //Final
				System.out.println("C : "+state);


//						send("C-->AS: AccessToken_Requested_With_RefreshToken","C-->AS: Service_Request_Completed"); //22
//						if(chosen.equals("C-->AS: AccessToken_Requested_With_RefreshToken")) {
//							state = "C-->AS: AccessToken_Requested_With_RefreshToken";
//							System.out.println("C : "+state);
//						}
//						else {
//							state = "Success"; //Final
//							System.out.println("C : "+state);
//						}

			/*		}
					else requestFailed();*/
//				}
			}
			else {
				state = "InvalidAccessToken"; //21
				System.out.println("C : "+state);
//				send("C-->AS: AccessToken_Requested_With_RefreshToken","Request_Failed"); //22
//				if(chosen.equals("C-->AS: AccessToken_Requested_With_RefreshToken")){
				send("AccessToken_Requested_With_RefreshToken");
					state = "AccessToken_Requested_With_RefreshToken"; //Final
					System.out.println("C : "+state);
					receive("New_AccessToken","Invalid_RefreshToken");
					if(chosen.equals("New_AccessToken")) {
						state = "New_AccessToken_RefreshToken"; //Final
						System.out.println("C : "+state);

						requestResource();
					}
					else {
						send("Request_Failed");
						//send("Request_Failed");
						requestFailed();
					}

//				}
//				else requestFailed();
			}

		//}
		//else requestFailed(); //19 End if C-->RS: Resource_Requested_With_AccessToken

	}

	public void requestFailed() {
		state = "Request_Failed";
		System.out.println("C : "+state);
	}

} //End Client Class
