<?php
/**
 * @property NotificationComponent $Notification
 * @property PermissionComponent $Permission
 */
class MeservicesController extends AppController
{
	
	var $uses = array('Expense','GroupExpense','Participant','Meal','AccessInfo', 'User');
	public $components = array('RequestHandler','MobileDetect','ImageUpload','Permission','Notification');

	private $app_name = "MessExpense";
	public $api_mess_version = "3";
	private $app_version = "1"; // 1= old expense date, 2= new expense date
	public $force_upgrade_status = "41";
	
    private $permission_status = "50";

	public function initialize()
	{
		 
		$this->api_mess_version = "3"; // new date change
		 
		$this->app_version = "1";
		$this->setDefaultTimeStamp();
	}
	
	
	
	private function validateExpense($expenseArray){
		
		$error = "";
		
		if(empty($expenseArray)){
			$error = "5";
		} 
		
				
		if($error == ""){
			if (!array_key_exists('title', $expenseArray)
				|| !array_key_exists('currency', $expenseArray) 
				|| !array_key_exists('language', $expenseArray)
				|| !array_key_exists('expense_type', $expenseArray)) {
				
				$error = "6";
			}
		}
		
		if($error == ""){
			if(strlen(trim($expenseArray["title"])) < 1 || mb_strlen(trim($expenseArray["title"]),'UTF-8')  > 50){
				$error = "7";
			} else if(strlen(trim($expenseArray["currency"])) < 1 || mb_strlen(trim($expenseArray["currency"]),'UTF-8')  > 3){
			    
			    if(mb_strlen(trim($expenseArray["currency"]), 'UTF-8')  > 3){
			        $expenseArray["currency"] =  substr(trim($expenseArray["currency"], 'UTF-8'), 0,3);
			        
			    } else {
			        
			        $error = "7";
			    }
				  
			} else if( mb_strlen(trim($expenseArray["description"]),'UTF-8')  > 150){
				$error = "7";
			} else if(strlen(trim($expenseArray["language"])) < 1 || mb_strlen(trim($expenseArray["language"]),'UTF-8')  > 3){
				$error = "7";
			} else if(strlen(trim($expenseArray["expense_type"])) != 1){
				$error = "7";
			}else if(!empty($expenseArray["user_id"]) && !is_numeric($expenseArray["user_id"])){
                $error = "7";
            }
			
		}
		
		return $error;
	}
	
	private function validateParticipant($ParticipantArray){
		$error = "";
		
		if(empty($ParticipantArray)){
			$error = "8";
		} 
		 
		 
		if($error == ""){
			foreach($ParticipantArray as $key=>$value){
				
				if (!array_key_exists('participant_id', $value)
				|| !array_key_exists('name',$value)
				|| !array_key_exists('is_creator', $value)) {
						
					$error = "9";
					break;
				}
				
				
				
				$nameArray[$key] = $value["name"];
				$idArray[$key] = $value["participant_id"];
				//check name length
				if(strlen(trim($value["name"])) < 1 || mb_strlen(trim($value["name"]), 'UTF-8') > PARTICIPENT_NAME_LENGTH){
				    if(mb_strlen(trim($value["name"]), 'UTF-8')  > PARTICIPENT_NAME_LENGTH){
				        $value["name"] =  substr(trim($value["name"], 'UTF-8'), 0,PARTICIPENT_NAME_LENGTH);
				        
				    } else {
				        
				        $error = "10";
				        break;
				    }
				}
				
				//check participant id format
				$arrayVal = explode("_", $value["participant_id"]);
				if(count($arrayVal) != 2){
					$error = "11";
					break;
				} else if(strlen(trim($arrayVal[0])) < 1 || strlen(trim($arrayVal[1])) < 1){
					$error = "11";
					break;
				}
			}
			
			//check name duplicacy
			if($error == ""){
				$previousLength = count($nameArray);
				$nameArray = array_unique($nameArray);
				if($previousLength != count($nameArray)){
					$error = "12";					 
				}
			}
			
			//check id duplicacy
			if($error == ""){
				$previousLength = count($idArray);
				$idArray = array_unique($idArray);
				if($previousLength != count($idArray)){
					$error = "12";					 
				}
			}
		}
		
		
		
		return $error;
	}
	
	private function validateExpenseList($GroupExpenseArray,$ParticipantArray,$isDeleteOperation = false){
		$error = "";
		
		/*if(empty($GroupExpenseArray)){
			$error = "13";
		}*/
		 if(!empty($GroupExpenseArray)){
		 
		if($error == ""){
			$participantIdList = array();
			
			foreach($ParticipantArray as $key1=>$value1){
				$participantIdList[$key1] = $value1["participant_id"];
			}
			
			foreach($GroupExpenseArray as $key=>$value){ 
				
				
				if (!array_key_exists('id', $value)
				|| !array_key_exists('what',$value)
				|| !array_key_exists('expense_date', $value)
				|| !array_key_exists('amount', $value)
				|| !array_key_exists('paid_by_participant_id', $value)
				|| !array_key_exists('is_reimbursement', $value)
				|| !array_key_exists('participant_amount', $value)
				|| !array_key_exists('isDetails', $value)
				|| !array_key_exists('type', $value)) {
						
					$error = "14";
					break;
				}
				
				//check id format is correct or not
				$arrayVal = explode("_", $value["id"]);
				if(count($arrayVal) != 2){
					$error = "15";
					break;
				} else if(strlen(trim($arrayVal[0])) < 1 || strlen(trim($arrayVal[1])) < 1){
					$error = "15";
					break;
				}
				
				$arrayVal = explode("-", $value["id"]);
				 
				if(count($arrayVal) != 3){
					$error = "16";
					break;
				} else if(strlen(trim($arrayVal[0])) < 1 
				|| strlen(trim($arrayVal[1])) < 1 
				|| strlen(trim($arrayVal[1])) > 5 
				|| strlen(trim($arrayVal[2])) < 1){
					$error = "16";
					break;
				}
			 
				
				//check the participant defined in expense exist in participant list or not

				if(!$isDeleteOperation) {
				 	$paidBy = $value["paid_by_participant_id"];
				 	if(!in_array($paidBy, $participantIdList)){
				 		$error = "17";
				 		break;
				 	}
				}
				
				 
				 if(isset($value["expense_type"]) && $value["expense_type"] == "2"
				 		&& $value["participant_amount"] == ""){
				 
				 } else {
				 		
					 
					 $totalAmt = 0;
					 
					 $partAmtArray = explode(",",$value["participant_amount"]);		
					 foreach($partAmtArray as $index=>$item){
					 	$partAmtDetailArray = explode("|",$item); 
					 	
					if(!$isDeleteOperation) {
                       if(!in_array($partAmtDetailArray[0], $participantIdList)){
                       $error = "18";
                       break 2;
                     }
                }
						 $totalAmt = $totalAmt + $partAmtDetailArray[2];
					 }
					//check total amount match with the part amount or not
					if(number_format($totalAmt, 2) != number_format($value["amount"], 2)){
					    
					    $var1 = number_format($totalAmt, 2);
					    $var2 = number_format($value["amount"], 2);
					    
					    $diff = $var1-$var2;
					    
					    
					    
					    if($diff < 0){
					        $diff = $diff * (-1);
					    }
					    
					    
					    $diff = number_format($diff, 2);
					    
					    if($diff > 0.01){
						  $error = "19";
						  break;
					    }
					}
				
				 }
				
				
				//check legth is ok or not
				
				if(strlen(trim($value["what"])) < 1 || mb_strlen(trim($value["what"]),'UTF-8') > 25){
				    
				    if(mb_strlen(trim($value["what"]), 'UTF-8')  > 25){
				        $value["what"] =  substr(trim($value["what"], 'UTF-8'), 0, 25);
				        
				    } else {
				        
				        $error = "20";
				        break;
				    }
				}
			}
			
			 
		}
		
	}
		
		return $error;
	}
	
	private function validateMealList($MealArray,$ParticipantArray){
		$error = "";
		
		//$isMessExpenseExist = false;
		$participantIdList = array();
		//check if: Invalid key or column name found for meal array
		foreach($MealArray as $key=>$value){			
			if (!array_key_exists('date', $value)
			|| !array_key_exists('meal_amount',$value)
			 ) {						
				$error = "41";
				break;
			}				
		}
		
		/*if( $error == "" && !empty($GroupExpenseArray)){
			foreach($GroupExpenseArray as $index=>$item){
				if($item["expense_type"] == "2"){
					$isMessExpenseExist = true;
					break;
				}
			}
		}*/
		
	
		if( $error == "" && !empty($ParticipantArray)){			
			foreach($ParticipantArray as $key1=>$value1){
				$participantIdList[$key1] = $value1["participant_id"];
			}		
		}
		//check if: Meal Expense has been added but there is not meal defined yet
		/*if( $error == "" && $isMessExpenseExist == true && empty($MealArray)){
			$error = "42";
			 break;
		}*/
		
		//check if: Invalid participant id found in meal which is not available in participant list
		if( $error == "" ){
			foreach($MealArray as $index=>$item){
				$MealSingleArray = explode(",",$item["meal_amount"]);
				
				foreach($MealSingleArray as $key=>$value){
					
					$MealSingleDetailsArray = explode("|",$value);
				
					if(count($MealSingleDetailsArray) != 4){
						$error = "43";//Meal format is not valid		 	 
						break 2;
					}else if(!in_array($MealSingleDetailsArray[0], $participantIdList)){
						$error = "44";//Invalid participant id found in meal which is not available in participant list					 	 
						break 2;
					} else if($MealSingleDetailsArray[1] < 0 || $MealSingleDetailsArray[2] < 0
						|| $MealSingleDetailsArray[3] < 0){
						$error = "45";//Invalid meal number found 
						break 2;
					}

				}
			}	
		
		}
	
		
		return $error;
	}
	
	 
	
	public function uploadMessExpense() {
		$object = $this->request->input('json_decode');
		
		if(!empty($object)){
			$data = $this->objectToArray($object);
		}
		
		$this->processMessExpense($data,false);
	}
	
	public function addMessExpense() {
		$object = $this->request->input('json_decode');
		
		if(!empty($object)){
			$data = $this->objectToArray($object);
		}
		
		$this->processMessExpense($data,true);
	}
	
	private function processMessExpense($data,$isTokenRequired) {
		$status = "+000";
        $status_desc = "Expense Data format is not correct!";
		$unique_url = "";
		$latestExpenseData = array();
		$archieved = false;
		$error = "";
	 
		//check maintenance mood
		if(MAINTENANCE_MOOD){
		    $status = "35";
		    $status_desc = "Service is in maintenance mood. Please try again later.";
		    $error = $status;
		} else if(empty($data)){
			$status = "31";
			$status_desc = "Invalid JSON input sent";
		} else {
		
			$expenseArray = (isset($data["Expense"])) ? $data["Expense"]:array();
			$ParticipantArray = (isset($data["Participant"])) ? $data["Participant"]:array();
			$GroupExpenseArray = $this->setDefaultWhat($data["GroupExpense"]);
			$MealArray = (isset($data["Meal"])) ? $data["Meal"]:array();
				
			if(isset($data["app_version"])){
				$this->app_version = $data["app_version"];
			}
				
			if(!empty($expenseArray["unique_url"]) && $expenseArray["unique_url"] != 'null' && !empty($expenseArray["id"])){
				if(!$this->isValidExpenseUniqueURL($expenseArray["unique_url"],"2")){
					$error = "31";
				} else{
					$result = $this->Expense->getGroupExpenseInfoByURL($expenseArray["unique_url"]);
					if(!empty($result)){
						$error = "32";
					} else {
						$archieved = true;
					}
				}
			}
			
			//validate token
			if($isTokenRequired){
				if(!isset($data["access_token"]) ||
						!isset($data["device_id"]) ||
						!isset($data["random_number"])){

                    if(isset($data["access_token"]) &&
                        isset($data["device_id"])  ){


                        $this->loadModel('AccessKey');
                        $data['random_number'] = $this->AccessKey->getAccessToken($data["device_id"]);

                        // $data["random_number"] = get from database by device id and order by created date desc

                        if(!$this->isValidToken($data["access_token"],$data["device_id"],$data["random_number"])){
                            //echo "some";exit;
                            $error = "57"; // token is not valid
                        } else {
                            $this->AccessKey->deleteAccessKey($data["device_id"]);
                        }
                    } else {

                        $error = "56"; //token is not given
                        //device id, random number, secret key =>  token
                    }
				} else if(!$this->isValidToken($data["access_token"],$data["device_id"],$data["random_number"])){
					$error = "57"; // token is not valid
				}
			}
				
			if($error == "") {
                $expenseArray['user_id'] = $data['user_id'];
                $expenseArray['create_user'] = $data['create_user'];
				$error = $this->validateExpense($expenseArray);
                // validate user id
                if($error == "" && (!empty($expenseArray['user_id'] || !empty($expenseArray['create_user'] )))){
                    $user = [];
                    if (!empty($expenseArray['user_id'])) {
                        $user = $this->User->getUserByUserId($expenseArray['user_id']);
                    } elseif (!empty($expenseArray['create_user'])) {
                        $user = $this->User->getUserByProfileId($expenseArray['create_user']);
                    }

                    if (empty($user) || empty($user['User'])) {
                        $error = "7";
                        $status = $error;
                        $status_desc = "User not found!";
                    }
                }
			}
		
			if($error == "") {
				$error = $this->validateParticipant($ParticipantArray);
					
				if($error == "") {
					$error = $this->validateExpenseList($GroupExpenseArray,$ParticipantArray);
					 
					if($error == "") {
						$error = $this->validateMealList($MealArray,$ParticipantArray);
						 
						if($error == "") {
							$expenseArray["participants"] = $ParticipantArray;
		
							// $expense_id = "sdfsf";
							$expenseArray["source"] = $this->getSource(new MobileDetectComponent());
							$expenseArray["ip"] = $this->getClientIp();
							$expenseArray["user_agent"] = $this->getUserAgent();
							$expenseArray["secret_key"] = $this->getSecretKey(5);
                            if(!empty($user['User'])){
                                $expenseArray['create_user'] = $user['User']['profile_id'];
                                $expenseArray['user_id'] =  $user['User']['id'];
                            }else{
                                $expenseArray['create_user'] = "system";
                                $expenseArray['user_id'] = null;
                            }
							if($this->app_version == "1") {
								$expenseArray["create_date"] = $this->getExpenseCreationDate($expenseArray["create_date"]);
							}
		
							$expenseIdStr = $this->Expense->createExpense($expenseArray,true,$archieved);
							if($expenseIdStr != "") {
								$expenseIdStrArr = explode(",",$expenseIdStr);
                                $imageUploadResponses = null;
								if(!empty($GroupExpenseArray)){
									foreach($GroupExpenseArray as $key=>$value){
										$idPartsArray = explode("-",$GroupExpenseArray[$key]["id"]);
										$GroupExpenseArray[$key]["id"] = $idPartsArray[0]."-".$idPartsArray[1]."-".$expenseIdStrArr[0];
									}
		
									//start check the expense date format and decide
									if($this->app_version == "1"){
										foreach($GroupExpenseArray as $key=>$value){
											$value["expense_date_old"] = $value["expense_date"];
											$value["expense_date"] = $this->getIntToStrDate($value["expense_date"]);
                                            $imageUploadResponse = $this->ImageUpload->AddImageBucket($value['addImages'],$value['id'],$expenseIdStrArr[1],$this->app_name);
                                            $value['images'] = $imageUploadResponse['images'];
											$GroupExpenseArray[$key] = $value;
                                            $imageUploadResponses[$key] = $imageUploadResponse['response'];
										}
									} else {
		
										foreach($GroupExpenseArray as $key=>$value){
											$value["expense_date_old"] = $this->getStrToIntDate($value["expense_date"]);
                                            $imageUploadResponse = $this->ImageUpload->AddImageBucket($value['addImages'],$value['id'],$expenseIdStrArr[1],$this->app_name);
                                            $value['images'] = $imageUploadResponse['images'];
											$GroupExpenseArray[$key] = $value;
                                            $imageUploadResponses[$key] = $imageUploadResponse['response'];
										}
									}

									$error = $this->GroupExpense->addMultipleGroupExpense($GroupExpenseArray,$expenseIdStrArr[0]);
								}
						 		
								if($error != ""){
									$status = "22";
									$status_desc = "MessXpense Data Saving Failed!";
								} else {
									//
									$unique_url = $expenseIdStrArr[1];
									$expense_id = $expenseIdStrArr[0];
		
									if(!empty($MealArray)){
		
										//start check the expense date format and decide
		
										if($this->app_version == "1"){
											foreach($MealArray as $key=>$value){
												$value["date_old"] = $value["date"];
												$value["date"] = $this->getIntToStrDate($value["date"]);
												$MealArray[$key] = $value;
											}
										} else {
		
											foreach($MealArray as $key=>$value){
												$value["date_old"] = $this->getStrToIntDate($value["date"]);
												$MealArray[$key] = $value;
											}	
										}
										$error = $this->Meal->addMultipleMeal($MealArray,$expenseIdStrArr[0]);
									}
		
		
									if($error != ""){
										$status = "46";
										$status_desc = "Meal Data Saving Failed!";
									} else {
											
										$latestExpenseData = $this->Expense->getGroupExpenseInfoByURL($unique_url);

                                        if(!empty($user['User'])) {

                                            $this->loadModel('GroupSetting');
                                            $mode = isset($data['GroupSetting']['is_restricted_mode'])?$data['GroupSetting']['is_restricted_mode']:0;
                                            $request = [
                                                'is_restricted_mode' => $mode,
                                                'expense_id' => $latestExpenseData['Expense']['id'],
                                                'unique_url' => $expenseIdStrArr[1]
                                            ];
                                            $groupSettingData = $this->GroupSetting->saveGroupSetting($request);
                                            if(!empty($groupSettingData['GroupSetting'])) {
                                                $latestExpenseData['GroupSetting'] = [
                                                    "categories" => $groupSettingData ['GroupSetting']['categories'],
                                                    "version" => $groupSettingData ['GroupSetting']['version'],
                                                    "is_restricted_mode" => $groupSettingData ['GroupSetting']['is_restricted_mode']
                                                ];
                                            }
                                            $permission_request = [
                                                'expense_id' => $latestExpenseData['Expense']['id'],
                                                'unique_url' => $expenseIdStrArr[1],
                                                'profile_id' => $user['User']['profile_id'],
                                                'user_id' => $user['User']['id'],
                                                "role"  => OWNER

                                            ];
                                            $PermissionTable = ClassRegistry::init('PermissionTable');
                                            $permission = $PermissionTable->addPermission($permission_request);
                                            if(!empty($permission)) {
                                                $latestExpenseData['Permissions'] =  [[
                                                    'profile_id' => $user['User']['profile_id'],
                                                    "role"  => OWNER
                                                ]];
                                            }

                                        }
										if(empty($latestExpenseData)) {
											$status = "34";
											$status_desc = "Data successfully inserted but can not retrieve latest data.Please try to reload again with unique URL.";
										} else {
		
											//reset expense date for old apps
											$groupExpensesList = $latestExpenseData["GroupExpense"];
											if($this->app_version == "1" && !empty($groupExpensesList)){
												foreach($groupExpensesList as $key=>$value){
													$groupExpensesList[$key]["expense_date"] = $value["expense_date"];
													//$groupExpensesList[$key]["expense_date_new"] = "";
												}
												$latestExpenseData["GroupExpense"] = $groupExpensesList;
											}
		
											//reset meal date for old apps
											$mealList = $latestExpenseData["Meal"];
											if($this->app_version == "1" && !empty($mealList)){
												foreach($mealList as $key=>$value){
													$mealList[$key]["date"] = $value["date"];
													//$mealList[$key]["date_new"] = "";
												}
												$latestExpenseData["Meal"] = $mealList;
											}

											$status = "+000";
											$status_desc = "SUCCESS";
		
											//insert/update access info
											$data["id"] = $latestExpenseData["Expense"]["id"];
											$data["unique_url"] = $latestExpenseData["Expense"]["unique_url"];
											$this->insertAccessInfo($data);
										}
									}
								}

								// add data to user group table and update myProfileUser firebase version
								if( isset($data['user_id'])
									&& !empty($data['user_id'])
									&& isset($data['unique_url'])
									&& !empty($data['unique_url'])
								) {
									$this->addUserGroupDuringExpenseCreate(
										$data['user_id'],
										$data["unique_url"], 
										"MessExpense");
								}

							} else {
								$status = "22";
								$status_desc = "Expense or Participant Data Saving Failed!";
							}
		
						} else {
							$status = $error;
							$status_desc = "Meal Data format is not valid";
						}
		
					} else {
						$status = $error;
						$status_desc = "WeXpense Data format is not valid";
					}
		
				} else {
					$status = $error;
					$status_desc = "Participant Data format is not valid";
				}
					
			} else {
				$status = $error;
				$status_desc = $status_desc;
			}
				
				
		}

		$input["status"] = $status;
		$input["status_desc"] = $status_desc;
		$input["api_version"] = $this->api_mess_version;

		if(!empty($error) || $status !="+000" ) {
            $input["input"] = $data;

            $this->loadModel('LogAppCrashes');
            $crash["unique_url"] = $unique_url;
            $crash["error_code"] = $status;
            $crash["error_desc"] = $status_desc;
            $crash["request"] = serialize($data);
            $crash["response"] = serialize($latestExpenseData);
            $crash["crash_date"] = $this->getSystemCurrentTimeStamp();
            $crash["ip"] = $this->getClientIp();
            $crash["device_info"] = $this->getUserAgent();
            $crash["expense_type"] = 2;
            $this->LogAppCrashes->insertLogAppCrashes($crash);
        } 

		//$input["input"] = $data;
		$input["data"] = $latestExpenseData;
		$input["expense_id"] = $expense_id;
		$input["unique_url"] = $unique_url;
		if(isset($imageUploadResponses) && !empty($imageUploadResponses)){
            $input["image_upload_response"] = $imageUploadResponses;
        }
			
		$this->set(array(
				'response' => $input,
				'_serialize' => array('response')
		));
			
			
		 
	}
	
	private function getSecretKey($length = 10){
		
		$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
	    $charactersLength = strlen($characters);
	    $randomString = '';
	    for ($i = 0; $i < $length; $i++) {
	        $randomString .= $characters[rand(0, $charactersLength - 1)];
	    }
	    
		return $randomString;

	}
	
	private function isParticipantInvolveInExpense($participantId,$expenseList){
		$result = false;
		
		if(!empty($expenseList)){
			foreach($expenseList as $key=>$value){
				if(trim($value["paid_by_participant_id"]) == trim($participantId)){
					$result = true;
					break;
				}	
				
				$participantAmtArray = explode(",",$value["participant_amount"]);
				foreach($participantAmtArray as $index=>$item){
					$participantAmtDetailsArray = explode("|",$item);
					if(trim($participantAmtDetailsArray[0]) == trim($participantId)){
						$result = true;
						break 2;
					}
				}

			 
			}			
		}
		
		
		return $result;
	}
	
	private function isParticipantInvolveInMeal($participantId,$mealList){
		$result = false;
		
		if(!empty($expenseList)){
			foreach($mealList as $key=>$value){ 
				
				$participantMealArray = explode(",",$value["meal_amount"]);
				foreach($participantMealArray as $index=>$item){
					$participantMealDetailsArray = explode("|",$item);
					if(trim($participantMealDetailsArray[0]) == trim($participantId)){
						$result = true;
						break 2;
					}
				}

			 
			}			
		}
		
		
		return $result;
	}
	
	private function isValidGroupExpense($paidByParticipantId,$amountString,$mergedParticipantIdList,$expense_type=1){
		$result = true;
		
	 
		
		if(!empty($mergedParticipantIdList)){
		 
			if(!in_array(trim($paidByParticipantId),$mergedParticipantIdList)){
				// echo "hello";
			 	$result = false;
			} else if($expense_type == 1){		 	
				$participantAmtArray = explode(",",$amountString);
				foreach($participantAmtArray as $index=>$item){
					$participantAmtDetailsArray = explode("|",$item);
					if(!in_array(trim($participantAmtDetailsArray[0]),$mergedParticipantIdList) ){
						$result = false;
						break;
					}
				}		 	
			 }
		} else {
			$result = false;
		}
		
		 
		return $result;
	}
	
	private function isValidMeal($meal_amount,$mergedParticipantIdList){
		
		$result = true;
		
		if(!empty($mergedParticipantIdList)){ 
			 		 	
			$mealAmtArray = explode(",",$meal_amount);
			foreach($mealAmtArray as $index=>$item){
				$mealAmtDetailsArray = explode("|",$item);
				if(!in_array(trim($mealAmtDetailsArray[0]),$mergedParticipantIdList) ){
					$result = false;
					break;
				}
			}			  
		} else {
			$result = false;
		}		
		 
		return $result;
		
	}
	
	private function isMealDateExistInDB($date,$dbMealList){
		
		$result = false;
		
		if(!empty($dbMealList)){ 
			foreach($dbMealList as $index=>$item){				 
				if($date == $item["date"]){
					$result = true;
					break;
				}
			}			  
		}		
		 
		return $result;
		
	}
	
	private function getReplacedValWithParticipantId($value,$mapRemoteAndWebId){
		
		 
		if(array_key_exists($value["paid_by_participant_id"], $mapRemoteAndWebId)){
			$value["paid_by_participant_id"] = $mapRemoteAndWebId[$value["paid_by_participant_id"]];								
		}
		
		$amountStrArray = explode(",",$value["participant_amount"]);
		foreach($amountStrArray as $index=>$item){
			$amountStrDetailArray = explode("|",$item);
			
			if(array_key_exists($amountStrDetailArray[0], $mapRemoteAndWebId)){
				$amountStrDetailArray[0] = $mapRemoteAndWebId[$amountStrDetailArray[0]];								
			}
			$amountStrArray[$index] = implode("|",$amountStrDetailArray);
		}
		
		$value["participant_amount"] = implode(",",$amountStrArray);
		
		 return $value;
						
	}
	
	
	private function getReplacedValWithParticipantIdForMeal($value,$mapRemoteAndWebId){
		
 	
		$mealStrArray = explode(",",$value["meal_amount"]);
		foreach($mealStrArray as $index=>$item){
			$mealStrDetailArray = explode("|",$item);
			
			if(array_key_exists($mealStrDetailArray[0], $mapRemoteAndWebId)){
				$mealStrDetailArray[0] = $mapRemoteAndWebId[$mealStrDetailArray[0]];								
			}
			$mealStrArray[$index] = implode("|",$mealStrDetailArray);
		}
		
		$value["meal_amount"] = implode(",",$mealStrArray);
		
		 return $value;
						
	}
	
	
	private function setExpenseLogInfo($dbExpense,$newExpense,$participantList,$oldCurrency,$newCurrency,$indicator){
		
		//$indicator = 1 means edited, $indicator = 2 means deleted
		if(!empty($participantList)){
			$newExpense["previous_desc"] = $this->getGeneratedLog($dbExpense,$participantList,$oldCurrency); //take from db expense
			
			if($indicator == 1){
				$newExpense["new_desc"] = $this->getGeneratedLog($newExpense,$participantList,$newCurrency); ;// take from $newExpense;
				
			} else if($indicator == 2){
				$newExpense["new_desc"] = "deleted";
			}
			 
			 
			$newExpense["previous_paid_by"] = $participantList[$dbExpense["paid_by_participant_id"]]["name"];
		}
		
		return $newExpense;
	}
	
	private function getGeneratedLog($expenseObj,$participantList,$currency){
		 $logStr = "";
		
		$logStr .= "[Title:".$expenseObj["what"]."],";
		$logStr .= "[PaidBy:".$participantList[$expenseObj["paid_by_participant_id"]]["name"]."],";
		$logStr .= "[Date:".$expenseObj["expense_date"]."],";
		$logStr .= "[Amount:".$expenseObj["amount"].' '.$currency."],";
		$logStr .= "[Involves:";
		
		$participantAmtStrArray = explode(",",$expenseObj["participant_amount"]);
		foreach($participantAmtStrArray as $key=>$value) {
			$dataArray = explode("|",$value);
			if($key == 0){
				$logStr .= $participantList[$dataArray[0]]["name"]."=".$dataArray[2];
			} else {
				$logStr .= ",".$participantList[$dataArray[0]]["name"]."=".$dataArray[2];
			}
		}
		$logStr .= "]";
		
		 
		
		return $logStr;
	}
 
	
	//Rules of Synchronization:
	/*#EditExpense
	 * 
	 * 1. Web and remote application version should be same
	 * 2. Expense related data should be modified then only it will update web Database.If nothing has been
	 * changed in remoate applicaiton, the value should be empty.(optional)
	 * 
	 * 
	 * 
	 * #AddGroupExpenseList
	= * 1. The participants who are involved in a particular group expense should be available 
	 * in merged participant list(merge between web and remote participant list).
	 * 
	 * 
	 * #EditGroupExpenseList
	 * 1. The record should be available in web database.
	 * 2. Web and remote application version should be same for a particular record.
	= * 3. The participant who are involved in the record, should be available in merged
	 * participant list(merge between web and remote participant list).
	 * 
	 * 
	 * 
	 * 
	 * 
	 * #DeleteGroupExpenseList
	 * 1. The record should be available in web database
	 * 2. Web and remote application version should be same for a particular record.
	 * 
	 * 
	 * 
	 * 
	 * #AddParticipantList
	 * 1. The name of the participant can not be duplicat in web database
	 * 
	 * 
	 * 
	 * 
	 * #EditParticipantList
	 * 1. The record should be available in web database
	 * 2. Web and remote application version should be same for a particular record.
	 * 3. The name of the participant can not be duplicat in web database
	 * 4. The name of the participant can not be available in give AddParticipantList(optional)
	 * 
	 * 
	 * #DeleteParticipantList
	 * 1. The record should be available in web database.
	 * 2. Web and remote application version should be same for a particular record.
	 * 3. The participant who created the account, can not be deleted.
	 * 4. The participant can not be exist in any web group expense as well as given add and edit group expense list( after as well as,not mendatory)
	 * 
	 * 
	 * 
	 * #AddMeal
	 * 1. The meal date should not exist in database
	 * 2. The particpant id exist in meal_amount should be available in merged participant list
	 * 
	 * #EditMeal
	 * 1. The meal data should be available in database
	 * 2. The participant id exist in meal_amount should be available in merged participant list
	 * 3. The version should be matchd with database version 
	 * 
	 * 
	 * #DeleteMeal
	 * 1. The meal date should be available in database
	 * 2. The version should be matched with database version 
	 * 
	 * 
	 * 
	 * 
	 * 
	 * 
	 */
	
	public function synMessExpense() {
		
		//actions
		// new participant should be Shimul,Masbha;id should be 221 and 222
		// The name "Ashraf" will be modified to Somen
		// The participants soup should be deleted
		
	 
		$status = "+000";
		$status_desc = "SUCCESS"; 
		$error = "";
		
		$latestExpenseData = array();
		$conflictArray = array();
		
		$object = $this->request->input('json_decode');
		
		if(!empty($object)){
			$data = $this->objectToArray($object);
		}

		//check maintenance mood
		if(MAINTENANCE_MOOD){
		    $status = "35";
		    $status_desc = "Service is in maintenance mood. Please try again later.";
		    $error = $status;
		} else if(empty($data)){
		   $status = "31";
		   $status_desc = "Invalid JSON input sent";
		}  else if(empty($data["unique_url"]) || $data["unique_url"] == ""){
			$status = "33";
			$status_desc = "Invalid Unique URL";
		}else if(isset($data["api_version"]) && !empty($data["api_version"]) && $this->isForceUpgradeRequire($data["api_version"], $this->api_mess_version)) {

            $status = $this->force_upgrade_status;
            $status_desc = "Client require force upgrade!";

        } else {
			$result = $this->Expense->getGroupExpenseInfoByURL($data["unique_url"]);
            $owner = false;
            if(!empty($result['Expense']) && !empty($data['user_id'])){
                $user = $this->User->getUserByUserId($data['user_id']);
                if(!empty($user['User'])){
                    $owner = ($result['Expense']['user_id'] == $user['User']['id']) || ($result['Expense']['create_user'] == $user['User']['profile_id']);
                }
            }
            if(!$owner) {
                $permission = $this->Permission->PermissionByUserId($data["unique_url"], $data['user_id']);
                if ($permission == NO_PERMIT) {
                    $this->set(array(
                        'response' => ['status' => $this->permission_status,
                            'status_desc' => "You are not authorized to this page.Please Provide valid user id."],
                        '_serialize' => array('response')
                    ));
                    return;
                }
            }
			//check   backup or archive data
			if(empty($result)){
			    
			    $this->loadModel('Backup');
			    
			    $this->Backup->restore($data["unique_url"]);
			    $result = $this->Expense->getGroupExpenseInfoByURL($data["unique_url"]);
			    
			}
			
			if(empty($result)){
				$status = "32";
				$status_desc = "Data not exist for the given unique URL";
			} else {
				
				//Conflict  Array
				$conflictArray["Expense"] = NULL;
				$conflictArray["addParticipant"] = NULL;
				$conflictArray["modifyParticipant"] = NULL;
				$conflictArray["deleteParticipant"] = NULL;
				$conflictArray["addGroupExpense"] = NULL;
				$conflictArray["modifyGroupExpense"] = NULL;
				$conflictArray["deleteGroupExpense"] = NULL;
				$conflictArray["addMeal"] = NULL;
				$conflictArray["modifyMeal"] = NULL;
				$conflictArray["deleteMeal"] = NULL;
				
				
				//get DB information
				$dbExpense = $result["Expense"];
				$dbGroupExpenseList = $result["GroupExpense"];
				$dbParticipantList = $result["Participant"];
				$dbMealList = $result["Meal"];
				
				//set data
				$currency =  $dbExpense["currency"];
				
				//get user's input
                $expenseArray = array();
                if(isset($data["Expense"]) && !empty($data["Expense"])){
                    $expenseArray = $data["Expense"];
                }

                $addParticipantArray = array();
                $modifyParticipantArray = array();
                $deleteParticipantArray = array();

                $addGroupExpenseArray = array();
                $modifyGroupExpenseArray = array();
                $deleteGroupExpenseArray = array();

                if (isset($data["addParticipant"]) && !empty($data["addParticipant"])) {
                    $addParticipantArray = $data["addParticipant"];
                }
                if (isset($data["modifyParticipant"]) && !empty($data["modifyParticipant"])) {
                    $modifyParticipantArray = $data["modifyParticipant"];
                }
                if (isset($data["deleteParticipant"]) && !empty($data["deleteParticipant"])) {
                    $deleteParticipantArray = $data["deleteParticipant"];
                }
                if (isset($data["addGroupExpense"]) && !empty($data["addGroupExpense"])) {
                    $addGroupExpenseArray = $this->setDefaultWhat($data["addGroupExpense"]);
                }
                if (isset($data["modifyGroupExpense"]) && !empty($data["modifyGroupExpense"])) {
                    $modifyGroupExpenseArray = $this->setDefaultWhat($data["modifyGroupExpense"]);
                }
                if (isset($data["deleteGroupExpense"]) && !empty($data["deleteGroupExpense"])) {
                    $deleteGroupExpenseArray = $this->setDefaultWhat($data["deleteGroupExpense"]);
                }

                $addMealArray = array();
                $modifyMealArray = array();
                $deleteMealArray = array();
                if (isset($data["addMeal"]) && !empty($data["addMeal"])) {
                    $addMealArray = $data["addMeal"];
                }
                if (isset($data["modifyMeal"]) && !empty($data["modifyMeal"])) {
                    $modifyMealArray = $data["modifyMeal"];
                }
                if (isset($data["deleteMeal"]) && !empty($data["deleteMeal"])) {
                    $deleteMealArray = $data["deleteMeal"];
                }
				
				$mergedParticipantIdList= array();
				$mergedParticipantNameList = array();
				
				
				if(isset($data["app_version"])){
					$this->app_version = $data["app_version"];
				}
				
				//Filter expense
				if(!empty($expenseArray) && $expenseArray["version"] < $dbExpense["version"] ){
					$conflictArray["Expense"] = $expenseArray;
					$expenseArray = NULL;
				} else if(!empty($expenseArray) ){
					$expenseArray["version"] = $expenseArray["version"]+1;
					$currency =  $expenseArray["currency"];
					if($expenseArray["version"] > 999){
						$expenseArray["version"] = 1;
					}
				}
				
				  
						
				//Filter participant List				
				if(!empty($dbParticipantList)){
					foreach($dbParticipantList as $key=>$value){
						$dbAsParticipantList[$value["participant_id"]] = $value;
						$dbParticipantNameList[$key] = $value["name"];
						array_push($mergedParticipantIdList,trim($value["participant_id"]));
						array_push($mergedParticipantNameList,trim($value["name"]));
					}		
				
					//reset delete participant list
					if(!empty($deleteParticipantArray)){
						if(empty($dbAsParticipantList)){
							$deleteParticipantArrayFinal = $deleteParticipantArray;
						} else{
							$i = 0;
							foreach($deleteParticipantArray as $key=>$value){
								if(array_key_exists($value["participant_id"],$dbAsParticipantList)
								&& $value["version"] == $dbAsParticipantList[$value["participant_id"]]["version"]
								&& $value["is_creator"] != "1"){
									//For delete,check the participant id has entry in db expense list,or given expense lsit
									//if exist,remove it from delete list
										
									if(!$this->isParticipantInvolveInExpense($value["participant_id"],$dbGroupExpenseList)
									&& !$this->isParticipantInvolveInMeal($value["participant_id"],$dbMealList)){
										$deleteParticipantArrayFinal[$i++] = $value;// Final ready
										if (($key = array_search(trim($value["participant_id"]), $mergedParticipantIdList)) !== false) {
											$mergedParticipantIdList = array_diff($mergedParticipantIdList, array($value["participant_id"]));
											$mergedParticipantNameList = array_diff($mergedParticipantNameList, array($value["name"]));
												
										}
									}
								} else {
									$conflictArray["deleteParticipant"][] = $value["participant_id"];
								}
							}
						}
					}
					 
						
					//reset edit participant list
					if(!empty($modifyParticipantArray) && !empty($dbAsParticipantList)){
						$i = 0;
						foreach($modifyParticipantArray as $key=>$value){
							if(array_key_exists($value["participant_id"],$dbAsParticipantList)
							&& $value["version"] == $dbAsParticipantList[$value["participant_id"]]["version"]
							&& !in_array($value["name"],$mergedParticipantNameList)){
								//For edit, check any participant already exist id DB or not which is mentioned in edit
								//if exist, just ignor the participant,otherwise edit it
				
								$modifyParticipantArrayFinal[$i++] = $value; // Final ready
							} else {
								$conflictArray["modifyParticipant"][] = $value["participant_id"];
							}
						}
							
					}
						
				} else {
					//if there are not data in database then just assign final
					$modifyParticipantArrayFinal = NULL;
					$deleteParticipantArrayFinal = NULL;
				}
							
							
						
				 
				
				//Filter Group Expense List 
				if(!empty($dbGroupExpenseList)){
					
					foreach($dbGroupExpenseList as $key=>$value){
						$dbAsGroupExpenseList[$value["id"]] = $value;
					}
					
					//reset edit group expense list
					if(!empty($modifyGroupExpenseArray)){
						if(empty($dbAsGroupExpenseList)){
							$modifyGroupExpenseArrayFinal = $modifyGroupExpenseArray;
						} else{
							$i = 0;
							
							//prepare log participant list to show modified participant name in logs
							if(!empty($dbAsParticipantList)){
								foreach($dbAsParticipantList as $key=>$value){
									$logParticipantList[$key] = $value;
								}
							}
							if(!empty($modifyParticipantArrayFinal)){
								foreach($modifyParticipantArrayFinal as $key=>$value){
									$logParticipantList[$value["participant_id"]] = $value;
								}
							}
							
							if(!empty($addParticipantArray)){
								foreach($addParticipantArray as $key=>$value){
									$logParticipantList[$value["participant_id"]] = $value;
								}
							}
							
							
							
							//set logs for modify						
							foreach($modifyGroupExpenseArray as $key=>$value){
							    
							//    echo $value["version"];
							 //   echo "<br/>";
							  //  echo  $dbAsGroupExpenseList[$value["id"]]["version"];exit;
							    
							    
								 if(array_key_exists($value["id"],$dbAsGroupExpenseList) 
								 	&& $value["version"] == $dbAsGroupExpenseList[$value["id"]]["version"]){
								     
								 	  
								 		
								 	$value = $this->setExpenseLogInfo($dbAsGroupExpenseList[$value["id"]],$value,$logParticipantList,$dbExpense["currency"],$currency,1);	
								 		
								 	$modifyGroupExpenseArrayFinal[$value["id"]] = $value; // Final ready
								 } else {
								 
								 	$conflictArray["modifyGroupExpense"][] = $modifyGroupExpenseArray[$key]["id"];
								 }
							}
						}
					}
					
					//reset delete group expense list					
					if(!empty($deleteGroupExpenseArray)){
						if(empty($dbAsGroupExpenseList)){
							$deleteGroupExpenseArrayFinal = $deleteGroupExpenseArray;
						} else{
							$i = 0;
							foreach($deleteGroupExpenseArray as $key=>$value){
								 if(array_key_exists($value["id"],$dbAsGroupExpenseList) 
								 && $value["version"] == $dbAsGroupExpenseList[$value["id"]]["version"]){
								 	$value = $this->setExpenseLogInfo($dbAsGroupExpenseList[$value["id"]],$value,$dbAsParticipantList,$dbExpense["currency"],$currency,2);
								 	$deleteGroupExpenseArrayFinal[$i++] = $value;// Final ready
								 } else {
								 	$conflictArray["deleteGroupExpense"][] = $value["id"];
								 }
							}
						}
					}
					
				} else {
					//if there are not data in database then just assign final
					$modifyGroupExpenseArrayFinal = NULL;
					$deleteGroupExpenseArrayFinal = NULL;
				}
				 
				
				
				//Filter Meal List
				if(!empty($dbMealList)){
					
					foreach($dbMealList as $key=>$value){
						$dbAsMealList[$value["id"]] = $value;
					}
					
					//reset edit Meal expense list
					if(!empty($modifyMealArray)){
						if(empty($dbAsMealList)){
							$modifyMealArrayFinal = NULL;
						} else{							 				
							foreach($modifyMealArray as $key=>$value){
								 if(array_key_exists($value["id"],$dbAsMealList) 
								 	&& $value["version"] == $dbAsMealList[$value["id"]]["version"]){ 
								 		$validModifyObj = true;
								 		
								 		foreach($dbAsMealList as $id=>$mealObj){
								 			if($value["id"] != $id && $value["date"] == $mealObj["date"] ){
								 				
								 				$validModifyObj = false;
								 				break;
								 			}
								 		}

								 	if($validModifyObj == true){
								 		$modifyMealArrayFinal[$value["id"]] = $value; // Final ready
								 	} else {
								 		$conflictArray["modifyMeal"][] = $value["date"];
								 	}
								 } else {
								 	$conflictArray["modifyMeal"][] = $value["date"];
								 }
							}
						}
					}
					
					//reset delete Meal list					
					if(!empty($deleteMealArray)){
						if(empty($dbAsMealList)){
							$deleteMealArrayFinal = NULL;
						} else{
						 
							foreach($deleteMealArray as $key=>$value){
								 if(array_key_exists($value["id"],$dbAsMealList) 
								 && $value["version"] == $dbAsMealList[$value["id"]]["version"]){
								 	 
								 	$deleteMealArrayFinal[$i++] = $value;// Final ready
								 } else {
								 	$conflictArray["deleteMeal"][] = $value["date"];
								 }
							}
						}
					}
					
				} else {
					//if there are not data in database then just assign final
					$modifyMealArrayFinal = NULL;
					$deleteMealArrayFinal = NULL;
				}
				
				
				//For add participant,check any item exist in dbParticipant or not				 
				if(!empty($addParticipantArray)){ 					
					foreach($addParticipantArray as $key=>$value){
						if(!in_array($value["name"],$dbParticipantNameList)){
					 		$addParticipantArrayFinal[] = $value;
					 		array_push($mergedParticipantIdList,trim($value["participant_id"]));	
					 		 
					 	} else {
					 		$conflictArray["addParticipant"][] = $value["participant_id"];
					 	}
					}
				}
				 
				
 				
				//Filter add group expense final list with merged participant list				
				if(!empty($addGroupExpenseArray)){
					foreach($addGroupExpenseArray as $key=>$value){
					    if($this->isValidGroupExpense($value["paid_by_participant_id"],$value["participant_amount"],$mergedParticipantIdList,$value["expense_type"])){
							
							//check if the expense already has been added
							$idArray = explode("-",$value["id"]);
							if(count($idArray) == 4){
								$uniqueDeviceExpenseID = $idArray[3];
								if(!$this->isItemAlreadyAdded($dbAsGroupExpenseList,$uniqueDeviceExpenseID) ){
									$value["syn_add_unique_id"] = $uniqueDeviceExpenseID;
									$addGroupExpenseArrayFinal[] = $value;
								}
									
							} else {
								$addGroupExpenseArrayFinal[] = $value;
							}
							
							
							
						} else {
							$conflictArray["addGroupExpense"][] = $value["id"];
						}
					}
				}
				
				//Filter add meal final list with merged participant list				
				if(!empty($addMealArray)){
					foreach($addMealArray as $key=>$value){
						 
						if($this->isValidMeal($value["meal_amount"],$mergedParticipantIdList)
							&& !$this->isMealDateExistInDB($value["date"],$dbMealList)){
								
								$addMealArrayFinal[] = $value;
						} else {
							$conflictArray["addMeal"][] = $value["date"];
						}
					}
				}
				
				
			 
				
				//Filter edit group expense final list with merged participant list	
				if(!empty($modifyGroupExpenseArrayFinal)){
					foreach($modifyGroupExpenseArrayFinal as $key=>$value){
					    if($this->isValidGroupExpense($value["paid_by_participant_id"],$value["participant_amount"],$mergedParticipantIdList,$value["expense_type"])){
							$modifyGroupExpenseArraySuperFinal[] = $value;
						} else {
							$conflictArray["modifyGroupExpense"][] = $value["id"];
						}
					}
				}
				
				//Filter edit meal final list with merged participant list	
				if(!empty($modifyMealArrayFinal)){
					foreach($modifyMealArrayFinal as $key=>$value){
						if($this->isValidMeal($value["meal_amount"],$mergedParticipantIdList)
							 ){
								
							$modifyMealArraySuperFinal[] = $value;
						}
					}
				}
				
				
				//generate and replace participant id
				if(!empty($addParticipantArrayFinal)){
					
					$maxParticipant = 0;
					$mapRemoteAndWebId = array();
					//get max id
					foreach($dbParticipantList as $key=>$value){
						$ParticipantIdArray = explode("_",$value["participant_id"]);
						if(trim($ParticipantIdArray[0]) > $maxParticipant){
							$maxParticipant = trim($ParticipantIdArray[0]);
						}
					}
					//echo "<pre>";
				//	print_r($addParticipantArrayFinal);exit;
					//generate map
					for($i=0;$i<count($addParticipantArrayFinal);$i++){
						$maxParticipant++;
						$mapRemoteAndWebId[$addParticipantArrayFinal[$i]["participant_id"]] = $maxParticipant."_0";
						//remove old and put new participant id from merged list						 
						foreach($mergedParticipantIdList as $si=>$item){
							 
							if(trim($item) == trim($addParticipantArrayFinal[$i]["participant_id"])){
								 
								$mergedParticipantIdList[$si] = $maxParticipant."_0";
							}
						}
						
						$addParticipantArrayFinal[$i]["participant_id"] = $maxParticipant."_0";
					}
					 
				}
					
					//replace all add expense and edit expense with the generated IDs
					if(!empty($addGroupExpenseArrayFinal)){
						$maxGroupSerialNo = 0;
						
						for($i=0;$i<count($addGroupExpenseArrayFinal);$i++){
							$value = $addGroupExpenseArrayFinal[$i]; 
							$addGroupExpenseArrayFinal[$i] = $this->getReplacedValWithParticipantId($value,$mapRemoteAndWebId);
						    if($i == 0){
						    	$firstPaidByParticipantId = $addGroupExpenseArrayFinal[0]["paid_by_participant_id"];
						    	
						    }
						
						    $participantIdArray = explode("-",$addGroupExpenseArrayFinal[$i]["id"]);
					    	if($participantIdArray[0] == $firstPaidByParticipantId){
					    		if($maxGroupSerialNo < intval($participantIdArray[1])){
					    			$maxGroupSerialNo = intval($participantIdArray[1]);
					    		}
					    	}
						} 
						
					}
					
				//replace all add meal and edit meal with the generated IDs
				if(!empty($addMealArrayFinal)){ 
					foreach($addMealArrayFinal as $key=>$value){
						$addMealArrayFinal[$key] =  $this->getReplacedValWithParticipantIdForMeal($value,$mapRemoteAndWebId);			
					}					 						
				}
					
					 
				if(!empty($modifyGroupExpenseArraySuperFinal)){					
					foreach($modifyGroupExpenseArraySuperFinal as $key=>$value){
						$modifyGroupExpenseArraySuperFinal[$key] = $this->getReplacedValWithParticipantId($value,$mapRemoteAndWebId);
					}
				}
					
				if(!empty($modifyMealArraySuperFinal)){
					
					foreach($modifyMealArraySuperFinal as $key=>$value){						
						 
						$modifyMealArraySuperFinal[$key] = $this->getReplacedValWithParticipantIdForMeal($value,$mapRemoteAndWebId);					
					}
				}
				
				
				
				//Reset add group expense Id with the genered ID
				if(!empty($addGroupExpenseArrayFinal)){		


					if(!empty($dbGroupExpenseList)){
						foreach($dbGroupExpenseList as $key=>$value){
							$value_array = explode("-",$value["id"]);
					
							$current_user_array = explode("-",$addGroupExpenseArrayFinal[0]["id"]);
					
							if($maxGroupSerialNo < intval($value_array[1]) && $current_user_array[0] == $value_array[0]){
								$maxGroupSerialNo = intval($value_array[1]);
							}
						}
					}
					
					
					for($i=0;$i<count($addGroupExpenseArrayFinal);$i++){
						$maxGroupSerialNo++;
						$addGroupExpenseArrayFinal[$i]["id"] = $firstPaidByParticipantId."-".sprintf("%05d", $maxGroupSerialNo)."-".$dbExpense["id"];
					}
				}
					
  
								
		}
	}


	if($status == "+000"){
		
		if(!empty($expenseArray)){
			$error = $this->validateExpense($expenseArray);
		}
		
		 //check add,edit,delete participant list
		 if($error == ""){
		 	
		 	if(!empty($addParticipantArrayFinal)){
		 		$error = $this->validateParticipant($addParticipantArrayFinal);
		 	}
		 	
		 	if($error == "" && !empty($modifyParticipantArrayFinal)){
		 		$error = $this->validateParticipant($modifyParticipantArrayFinal);
		 	}
		 	
		 	if($error == "" && !empty($deleteParticipantArrayFinal)){
		 		$error = $this->validateDeleteParticipant($deleteParticipantArrayFinal);
		 	}
		 	
		 	if($error == ""){
		 		//set merged participant object
		 		foreach($mergedParticipantIdList as $key=>$value){
		 			$participantObjList[$key]["id"] = $value;
		 			$participantObjList[$key]["participant_id"] = $value;
		 			
		 		}
		 		
		 		//check add,edit and delete expense list
		 		 if(!empty($addGroupExpenseArrayFinal)){
		 			$error = $this->validateExpenseList($addGroupExpenseArrayFinal,$participantObjList);
		 		 }
		 		
		 		 
		 		if($error == "" && !empty($modifyGroupExpenseArraySuperFinal)){
		 			//Set logs for the modify expense activity
		 			
		 			$error = $this->validateExpenseList($modifyGroupExpenseArraySuperFinal,$participantObjList);
		 		}
		 		if($error == "" && !empty($deleteGroupExpenseArrayFinal)){
		 			//set logs for expense delete activity
		 			$error = $this->validateExpenseList($deleteGroupExpenseArrayFinal,$participantObjList,true);
		 		}
		 		//echo "<pre>";
		 		//print_r($deleteParticipantArrayFinal);exit;
		 		if($error == ""){
		 			
			 		//check add,edit and delete expense list
			 		 if(!empty($addMealArrayFinal)){
			 			$error = $this->validateMealList($addMealArrayFinal,$participantObjList);
			 		 } 
			 		 
			 		if($error == "" && !empty($modifyMealArraySuperFinal)){
			 			//Set logs for the modify expense activity
			 			
			 			$error = $this->validateMealList($modifyMealArraySuperFinal,$participantObjList);
			 		}
			 		if($error == "" && !empty($deleteMealArrayFinal)){			 			 
			 			$error = $this->validateMealList($deleteMealArrayFinal,$participantObjList);
			 		}
		 			
		 			
			 		if($error == ""){
			 			//start from here!
			 			if(!empty($expenseArray)){
			 				$expenseArray["participants"] = $addParticipantArrayFinal;
			 				$expenseArray["source"] = $this->getSource(new MobileDetectComponent());
                            if($permission != VIEW_PERMIT) {
                                $response = $this->Expense->modifyExpense($expenseArray);
                            }
			 			}
			 			
			 			if(empty($response)){
			 				//$dbExpense
			 				
			 				//add multiple participants
			 			
			 				if(!empty($addParticipantArrayFinal) && $permission != VIEW_PERMIT){
			 					$error = $this->Participant->addMultipleParticipant($addParticipantArrayFinal,$dbExpense["id"]);
			 				}
			 				
			 				
			 				//edit multiple participants
			 				if($error == "" && !empty($modifyParticipantArrayFinal) && $permission != VIEW_PERMIT){
			 					$error = $this->Participant->modifyMultipleParticipant($modifyParticipantArrayFinal);
			 				}
			 			
			 				//add group expense
			 				if($error == "" &&  !empty($addGroupExpenseArrayFinal) && $permission != VIEW_PERMIT){
                                $imageUploadResponses = null;
			 					//start check the expense date format and decide
			 					if($this->app_version == "1"){	
			 						foreach($addGroupExpenseArrayFinal as $key=>$value){
			 							$value["expense_date_old"] = $value["expense_date"];
			 							$value["expense_date"] = $this->getIntToStrDate($value["expense_date"]);

                                        $imageUploadResponse = $this->ImageUpload->AddImageBucket($value['addImages'],$value['id'],$data['unique_url'],$this->app_name);
                                        $value['images'] = $imageUploadResponse['images'];
                                        $addGroupExpenseArrayFinal[$key] = $value;
                                        $imageUploadResponses[$key] =  $imageUploadResponse['response'];

			 						}
		 						} else {

		 							foreach($addGroupExpenseArrayFinal as $key=>$value){
		 									
		 								if(!$this->isValidNewExpenseDate($value["expense_date"])){ //remove later
		 										
		 									$tmpArray = explode("-",$value["expense_date"]);
		 									if(count($tmpArray) == "1"){
		 										$value["expense_date_old"] = $value["expense_date"];
		 										$value["expense_date"] = $this->getIntToStrDate($value["expense_date"]);
		 									} else {
		 										$error = "22";
		 										break;
		 									}
		 								} else {
		 									$value["expense_date_old"] = $this->getStrToIntDate($value["expense_date"]);
		 								}

                                        $imageUploadResponse = $this->ImageUpload->AddImageBucket($value['addImages'],$value['id'],$data['unique_url'],$this->app_name);
                                        $value['images'] = $imageUploadResponse['images'];
                                        $addGroupExpenseArrayFinal[$key] = $value;
                                        $imageUploadResponses[$key] =  $imageUploadResponse['response'];

		 							}
		 								
		 						}
		 						if(empty($error))
			 					$error = $this->GroupExpense->addMultipleGroupExpense($addGroupExpenseArrayFinal,$dbExpense["id"]);
			 				}
			 				
			 				//edit group expense
			 				if($error == "" &&  !empty($modifyGroupExpenseArraySuperFinal) && $permission != VIEW_PERMIT){
			 					
			 					if($this->app_version == "1"){
			 						foreach($modifyGroupExpenseArraySuperFinal as $key=>$value){
			 							$value["expense_date_old"] = $value["expense_date"];
			 							$value["expense_date"] = $this->getIntToStrDate($value["expense_date"]);

			 							$modifyGroupExpenseArraySuperFinal[$key] = $value;
			 						}
			 					} else {
			 						foreach($modifyGroupExpenseArraySuperFinal as $key=>$value){
			 								
			 							if(!$this->isValidNewExpenseDate($value["expense_date"])){ //remove later
			 									
			 								$tmpArray = explode("-",$value["expense_date"]);
			 								if(count($tmpArray) == "1"){
			 									$value["expense_date_old"] = $value["expense_date"];
			 									$value["expense_date"] = $this->getIntToStrDate($value["expense_date"]);
			 								} else {
			 									$error = "22";
			 									break;
			 								}
			 							} else {
			 								$value["expense_date_old"] = $this->getStrToIntDate($value["expense_date"]);
			 							}

                                        $dbimages = $this->GroupExpense->getImagesById($value['id']);
                                        $deleted_image_response = $this->ImageUpload->DeleteSingleImageBucket($dbimages['GroupExpense']['images'],$value['id'],$data["unique_url"],$this->app_name,$value['deleteImages']);

                                        $upload_image_response = $this->ImageUpload->ModifyImageBucket($deleted_image_response['images'],$value['id'],$data["unique_url"],$this->app_name,$value['addImages']);

                                        $value['images'] = $upload_image_response['images'];
			 							$modifyGroupExpenseArraySuperFinal[$key] = $value;
                                        if(!empty($upload_image_response['response']['message'])){
                                            $conflictArray["modifyGroupExpense"][$value['id']][] = $upload_image_response['response']['message'];
                                        }
			 						}
			 					}
			 					
			 					if(empty($error))
			 					$error = $this->GroupExpense->modifyMultipleGroupExpense($modifyGroupExpenseArraySuperFinal,$dbExpense["id"]);
			 				}
			 					
			 				
			 				//delete group expense
			 				if($error == "" &&  !empty($deleteGroupExpenseArrayFinal) && $permission != VIEW_PERMIT){
			 					$error = $this->GroupExpense->deleteMultipleGroupExpense($deleteGroupExpenseArrayFinal,$dbExpense["id"]);

                                 if(empty($error)) {
                                     $imageDeleteResponse = $this->ImageUpload->DeleteImageBucket($deleteGroupExpenseArrayFinal, $data['unique_url'],$this->app_name);
                                 }
			 				}
			 				
			 				
			 				//add meal expense
			 				if($error == "" &&  !empty($addMealArrayFinal) && $permission != VIEW_PERMIT){
			 					
			 					if($this->app_version == "1"){
			 						foreach($addMealArrayFinal as $key=>$value){
			 							$value["date_old"] = $value["date"];
			 							$value["date"] = $this->getIntToStrDate($value["date"]);
			 							$addMealArrayFinal[$key] = $value;
			 						}
			 					} else {
			 						foreach($addMealArrayFinal as $key=>$value){
			 							
			 							if(!$this->isValidNewExpenseDate($value["date"])){ //remove later
			 									
			 								$tmpArray = explode("-",$value["date"]);
			 								if(count($tmpArray) == "1"){
			 									$value["date_old"] = $value["date"];
			 									$value["date"] = $this->getIntToStrDate($value["date"]);
			 								} else {
			 									$error = "22";
			 									break;
			 								}
			 							} else {
			 								$value["date_old"] = $this->getStrToIntDate($value["date"]);
			 							}		 							 
			 							$addMealArrayFinal[$key] = $value;
			 						}			 							
			 					}
			 					if(empty($error))
			 					$error = $this->Meal->addMultipleMeal($addMealArrayFinal,$dbExpense["id"]);
			 				}
			 				
			 				//edit meal expense
			 				if($error == "" &&  !empty($modifyMealArraySuperFinal) && $permission != VIEW_PERMIT){
			 					
			 					if($this->app_version == "1"){
			 						foreach($modifyMealArraySuperFinal as $key=>$value){
			 							$value["date_old"] = $value["date"];
			 							$value["date"] = $this->getIntToStrDate($value["date"]);
			 							$value["old_date"] = $this->getIntToStrDate($value["old_date"]);

			 							$modifyMealArraySuperFinal[$key] = $value;
			 						}
			 					} else {
			 						foreach($modifyMealArraySuperFinal as $key=>$value){
			 							
			 							if(!$this->isValidNewExpenseDate($value["date"])){ //remove later
			 									
			 								$tmpArray = explode("-",$value["date"]);
			 								if(count($tmpArray) == "1"){
			 									$value["date_old"] = $value["date"];
			 									$value["date"] = $this->getIntToStrDate($value["date"]);
			 									$value["old_date"] = $this->getIntToStrDate($value["old_date"]);
			 								} else {
			 									$error = "22";
			 									break;
			 								}
			 							} else {
			 								$value["date_old"] = $this->getStrToIntDate($value["date"]);
			 							}

			 							$modifyMealArraySuperFinal[$key] = $value;
			 						}
			 					}
			 					
			 					if(empty($error))
			 					$error = $this->Meal->modifyMultipleMeal($modifyMealArraySuperFinal,$dbExpense["id"]);
			 				}
			 					
			 				
			 				//delete meal expense
			 				if($error == "" &&  !empty($deleteMealArrayFinal) && $permission != VIEW_PERMIT){
			 					$error = $this->Meal->deleteMultipleMeal($deleteMealArrayFinal,$dbExpense["id"]);
			 				} 
		 					
			 				//delete multiple participant
			 				if($error == "" &&  !empty($deleteParticipantArrayFinal) && $permission != VIEW_PERMIT){
			 					$error = $this->Participant->deleteMultipleParticipant($deleteParticipantArrayFinal);
			 				}
			 				
			 				 
			 			 				
			 				if($error != ""){
			 					$status = "22";
			 					$status_desc = "Participant/Group/Meal Expense Update fails";
			 				} else {
			 					$latestExpenseData = $this->Expense->getGroupExpenseInfoByURL($dbExpense["unique_url"]);

                                if (!empty($latestExpenseData['Expense'])) {
                                    $latestExpenseData['Expense']['version'] = $latestExpenseData['Expense']['version'] + 1;
                                    $this->Expense->save($latestExpenseData);
                                }

                                $this->loadModel('GroupSetting');
                                $groupSettingData = $this->GroupSetting->getGroupSettingByURL($dbExpense["unique_url"],true);
                                if(!empty($groupSettingData)){
                                    $latestExpenseData['groupsettings'] = $groupSettingData;
                                }
                                $this->loadModel('PermissionTable');
                                $permissions = $this->PermissionTable->getPermissionByUrl($dbExpense["unique_url"]);
                                if(!empty($groupSettingData) && $groupSettingData['is_restricted_mode'] == 1){
                                    $permitted_users = $permissions;
                                }else{
                                    $userGroup = ClassRegistry::init('UserGroup');
                                    $user_groups = $userGroup->find('all', [
                                        'conditions' => [
                                            'UserGroup.unique_url' => $dbExpense["unique_url"]
                                        ],
                                        'fields' => ['UserGroup.user_id']
                                    ]);
                                    $permitted_users = array_map(function ($item) {
                                        return [
                                            'user_id' => $item['UserGroup']['user_id']
                                        ];
                                    }, $user_groups);
                                }

                                $permissions = array_map(function ($permission) {
                                    unset($permission['user_id']);
                                    return $permission;
                                }, $permissions);
                                $addPermissions = array_column($permissions, 'profile_id');
                                if (!in_array($latestExpenseData['Expense']['create_user'], $addPermissions)) {
                                    $permissionlist[] =  ['profile_id'=>$latestExpenseData['Expense']['create_user'],'role'=>OWNER];
                                }

                                if(!empty($permissions || !empty($permissionlist))){
                                    $permissionlist = array_merge($permissionlist ?? [], $permissions);
                                    $latestExpenseData['Permissions'] = $permissionlist;
                                }

			 					if(empty($latestExpenseData)){
			 						$status = "25";
			 						$status_desc = "Expense  Data Updated but data fetching failed!";
			 					} else {
			 						$status = "+000";
			 						$status_desc = "SUCCESS";
			 						
			 						//insert/update access info
			 						$data["id"] = $latestExpenseData["Expense"]["id"];
			 						$data["unique_url"] = $latestExpenseData["Expense"]["unique_url"];
			 						$this->insertAccessInfo($data);
			 						
			 						//reset expense date for old apps
			 						$groupExpensesList = $latestExpenseData["GroupExpense"];
			 						if($this->app_version == "1" && !empty($groupExpensesList)){
			 							foreach($groupExpensesList as $key=>$value){
			 								$groupExpensesList[$key]["expense_date"] = $value["expense_date"];
			 								//$groupExpensesList[$key]["expense_date_new"] = "";
			 							}
			 							$latestExpenseData["GroupExpense"] = $groupExpensesList;
			 						}
			 						
			 						//reset meal date for old apps
			 						$mealList = $latestExpenseData["Meal"];
			 						if($this->app_version == "1" && !empty($mealList)){
			 							foreach($mealList as $key=>$value){
			 								$mealList[$key]["date"] = $value["date"];
			 								//$mealList[$key]["date_new"] = "";
			 							}
			 							$latestExpenseData["Meal"] = $mealList;
			 						}
			 						
			 						
			 					}
			 					
			 				}
			 				
			 			} else {
			 				$status = "22";
			 				$status_desc = "Expense  Data Update Failed!";
			 			} 
			 		} else {
			 			
			 			$status = $error;
		 				$status_desc = "Meal Data format is not valid";
			 		} 
		 			
		 		} else {
		 			$status = $error;
		 			$status_desc = "MessXpense Data format is not valid";
		 		}
		 		
		 	} else {
		 		$status = $error;
		 		$status_desc = "Participant Data format is not valid";
		 	}
		 	
		 } else {
		 	$status = $error;
		 	$status_desc = "Expense Data format is not valid";
		 }
		 
		 
	}

    if($status == $this->force_upgrade_status) {
        $status = "+000"; // return succees without execution
    }
		
	$input["status"] = $status;
	$input["status_desc"] = $status_desc;
	$input["api_version"] = $this->api_mess_version;

	if(!empty($error) || $status !="+000" ) {
		$input["input"] = $data;

		$this->loadModel('LogAppCrashes');
		$crash["unique_url"] = $data["unique_url"];
		$crash["error_code"] = $status;
		$crash["error_desc"] = $status_desc;
		$crash["request"] = serialize($data);
		$crash["response"] = serialize($latestExpenseData);
		$crash["crash_date"] = $this->getSystemCurrentTimeStamp();
		$crash["ip"] = $this->getClientIp();
		$crash["device_info"] = $this->getUserAgent();
		$crash["expense_type"] = 2;
		$this->LogAppCrashes->insertLogAppCrashes($crash);
	}

    if($permission == VIEW_PERMIT && !empty($data['Expense'])){
        $permission_conflict["Expense"] = $data['Expense'];
    }
    if($permission == VIEW_PERMIT && !empty($data['addGroupExpense'])){
        $permission_conflict["addGroupExpense"] = $data['addGroupExpense'];
    }
    if($permission == VIEW_PERMIT && !empty($data['modifyGroupExpense'])){
        $permission_conflict["modifyGroupExpense"] = $data['modifyGroupExpense'];
    }
    if($permission == VIEW_PERMIT && !empty($data['deleteGroupExpense'])){
        $permission_conflict["deleteGroupExpense"] = $data['deleteGroupExpense'];
    }
    if($permission == VIEW_PERMIT && !empty($data['addParticipant'])){
        $permission_conflict["addParticipant"] = $data['addParticipant'];
    }
    if($permission == VIEW_PERMIT && !empty($data['modifyParticipant'])){
        $permission_conflict["modifyParticipant"] = $data['modifyParticipant'];
    }
    if($permission == VIEW_PERMIT && !empty($data['deleteParticipant'])){
        $permission_conflict["deleteParticipant"] = $data['deleteParticipant'];
    }
    if($permission == VIEW_PERMIT && !empty($data['addMeal'])){
        $permission_conflict["addMeal"] = $data['addMeal'];
    }
    if($permission == VIEW_PERMIT && !empty($data['modifyMeal'])){
        $permission_conflict["modifyMeal"] = $data['modifyMeal'];
    }
    if($permission == VIEW_PERMIT && !empty($data['deleteMeal'])){
        $permission_conflict["deleteMeal"] = $data['deleteMeal'];
    }

	//$input["input"] = $data;
	$input["data"] = $latestExpenseData;
	$input["conflict"] = $conflictArray;
    if($permission == VIEW_PERMIT){
        $input["permission_conflict"] = $permission_conflict;
    }
    if(isset($imageUploadResponses) && !empty(array_filter($imageUploadResponses))){
        $input["upload_image_response"] = $imageUploadResponses;
    }
    if(isset($imageDeleteResponse) && !empty(array_filter($imageDeleteResponse))) {
        $input["remove_image_response"] = $imageDeleteResponse;
    }
    if(isset($upload_image_response['response'])&& !empty($upload_image_response['response'])){
        $input['modify_mess_expense']['add_images'] = $upload_image_response['response'];
    }
    if(isset($deleted_image_response['response']) && !empty($deleted_image_response['response'])){
        $input['modify_mess_expense']['delete_images'] = $deleted_image_response['response'];
    }

        $conflict = (!empty($permitted_users) && empty($conflictArray['Expense'])
            && empty($conflictArray['addParticipant'])
            && empty($conflictArray['modifyParticipant'])
            && empty($conflictArray['deleteParticipant'])
            && empty($conflictArray['addGroupExpense'])
            && empty($conflictArray['modifyGroupExpense'])
            && empty($conflictArray['deleteGroupExpense']));
        $expense_validate =  (!empty($addGroupExpenseArray) || !empty($modifyGroupExpenseArray)|| !empty($deleteGroupExpenseArray));

        if($conflict && $expense_validate){
            $users = array_column($permitted_users, 'user_id');
            $users = array_diff($users, array($data['user_id']));
            $title = $dbExpense["title"];
            $operation = '';
            $expense['unique_url'] = $dbExpense["unique_url"];
            if(!empty($addGroupExpenseArray)){
                $expense['expenses']['add'] =  array_map(function ($addGroupExpense) {
                    return $addGroupExpense['id'];
                },array_slice($addGroupExpenseArray,0,2));
                $operation = $operation.'added ';
            }
            if(!empty($modifyGroupExpenseArray)){
                $expense['expenses']['update'] = array_map(function ($modifyGroupExpense) {
                    return $modifyGroupExpense['id'];
                }, array_slice($modifyGroupExpenseArray,0,2));
                if(empty($operation)){
                    $operation = $operation.'updated ';
                }else{
                    $operation = $operation.',updated ';
                }

            }
            if(!empty($deleteGroupExpenseArray)){
                $expense['expenses']['delete'] = array_map(function ($deleteGroupExpense) {
                    return $deleteGroupExpense['id'];
                }, array_slice($deleteGroupExpenseArray,0,2));
                if(empty($operation)){
                    $operation = $operation.'deleted ';
                }else{
                    $operation = $operation.',deleted ';
                }

            }
            $body = "Expenses have been {$operation}in {$dbExpense["title"]} group.";
            $expense['expenses'] = json_encode($expense['expenses']);
            $expense['title'] = $title;
            $expense['body'] = $body;
            if(!empty($users)) {
                $this->Notification->send($users, $expense);
            }
        }
	$this->set(array(
			'response' => $input,
			'_serialize' => array('response')
	));  	 
		  
}
	
	
private function insertAccessInfo($data){
	//insert data into the table access_infos
	$accessInfoData["id"] = $data["id"];
	$accessInfoData["unique_url"] = $data["unique_url"];
	$accessInfoData["access_time"] = $this->getSystemCurrentTimeStamp();

	$error = $this->AccessInfo->saveAccessInfo($accessInfoData);
}

}