package com.selfservit.util;

import android.annotation.TargetApi;
import android.content.Context;
import android.database.Cursor;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;

import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;


public class mInterfaceUtil {
	LocationManager locationManager;
	LocationListener locationListener;
	public static String packageName = "mservice";
	public static final Locale locale = Locale.US;

	/*FOR GETTING CURRENT LOCATION */
	public String getLocation(Context context) {
		String latitude = "",
				longitude = "";

		String currentLine, lastKnownLocation = "";
		try {
			BufferedReader readerObj = new BufferedReader(new FileReader(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/LastKnownLocation.txt")));
			while ((currentLine = readerObj.readLine()) != null) {
				lastKnownLocation = currentLine;
			}
			readerObj.close();
			String[] splitStr = lastKnownLocation.split(",");
			latitude = splitStr[0];
			longitude = splitStr[1];
		} catch (Exception e) {
			e.printStackTrace();
		}

		//*** SUBSTRING LATITUDE,LONGITUDE IF GREATER THAN 10 POINTS ***//
		if (latitude.length() > 10) {
			latitude = latitude.substring(0, 10);
		}
		if (longitude.length() > 10) {
			longitude = longitude.substring(0, 10);
		}
		//*** RETURN LATITUDE,LONGITUDE VALUE IN JSON OBJECT FORMAT ***//
		return "{\"lat\":" + "\"" + latitude + "\"" + ",\"lon\":" + "\"" + longitude + "\"}";
	}

	/*FOR CHECK LOCATION SERVICE SETTING IS ENABLED OR NOT */
	public String checkLocation(Context context) {
		Boolean isEnabled = false;

		//*** REGISTER THE LOCATION MANAGER *** //
		locationManager = (LocationManager) context.getSystemService(context.LOCATION_SERVICE);
		//*** CHECK LOCATION SETTING ENABLED OR NOT ***//
		isEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

		if (!isEnabled) {
			isEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
		}

		return String.valueOf(isEnabled);
	}

	/*FOR CHECK QUEUE IS PROCESSING OR NOT */
	public String getSyncIndicator(Context context) {
		File queueFile, queueFolder;
		Boolean syncIndication = false;
		try {
			queueFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/database/queue_mgr.txt");
			queueFolder = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/database/queue");
			if (queueFile.exists()) {
				if (queueFile.length() == 0) {
					syncIndication = true;
				}
			} else {
				syncIndication = true;
			}
			if (syncIndication) {
				if (queueFolder.exists()) {
					if (queueFolder.listFiles().length != 0) {
						syncIndication = false;
					}
				}
			}
			return String.valueOf(syncIndication);
		} catch (Exception e) {
			return String.valueOf(e);
		}

	}

	/* COPY A FILE FROM ONE LOCATION TO ANOTHER LOCATION */
	public void copyFile(CallbackContext callbackContext, JSONArray arguments) {
		JSONObject inputFileObj;
		String srcFilePath,
				srcFileName,
				desFilePath,
				desFileName,
				queueCopyPath,
				queueCopyFileName;
		InputStream srcFileReader;
		OutputStream desFileWriter, queueFileWriter;
		int srcFileSize;
		byte[] buf;
		File sourceFileObj, desFileObj, queueFileObj;
		try {
			for (int index = 0; index < arguments.length(); index++) {
				inputFileObj = arguments.getJSONObject(index);
				srcFilePath = inputFileObj.optString("srcPath").toString();
				srcFileName = inputFileObj.optString("srcFile").toString();
				desFilePath = "/sdcard/" + inputFileObj.optString("desPath").toString();
				desFileName = inputFileObj.optString("desFile").toString();
				queueCopyPath = "/sdcard/" + inputFileObj.optString("queueAttachPath").toString();
				queueCopyFileName = inputFileObj.optString("queueAttachFile").toString();
				sourceFileObj = new File(srcFilePath + "/" + srcFileName);
				desFileObj = new File(desFilePath + "/" + desFileName);
				queueFileObj = new File(queueCopyPath + "/" + queueCopyFileName);
				//** CHECK DESTINATION FILE PATH EXITS OR NOT **//
				if (!new File(desFilePath).exists()) {
					new File(desFilePath).mkdirs();
				}
				if (!new File(queueCopyPath).exists()) {
					new File(queueCopyPath).mkdirs();
				}
				//** CHECK SOURCE FILE EXITS OR NOT **//
				if (sourceFileObj.exists()) {
					srcFileReader = new FileInputStream(sourceFileObj);
					desFileWriter = new FileOutputStream(desFileObj);
					buf = new byte[1024];
					//** WRITE SOURCE FILE INTO CONTENT_STORE DESTINATION PATH **//
					while ((srcFileSize = srcFileReader.read(buf)) > 0) {
						desFileWriter.write(buf, 0, srcFileSize);
					}
					srcFileReader.close();
					desFileWriter.close();

					srcFileReader = new FileInputStream(sourceFileObj);
					queueFileWriter = new FileOutputStream(queueFileObj);
					buf = new byte[1024];
					//** WRITE SOURCE FILE INTO QUEUE DESTINATION PATH **//
					while ((srcFileSize = srcFileReader.read(buf)) > 0) {
						queueFileWriter.write(buf, 0, srcFileSize);
					}
					srcFileReader.close();
					queueFileWriter.close();
				} else {
					callbackContext.error("failure");
				}
			}
			deleteFilesFromDirectory();
			callbackContext.success("success");
		} catch (Exception e) {
			callbackContext.error(e.getMessage());
		}
	}

	public void queueProcessor(CallbackContext callbackContext) {
		String statusIndication = "false";
		String breakIndication = "false";
		try {
			String clientID, countryCode, userID, clientUrl;
			BufferedReader myAccountsFileReader;
			StringBuilder myAccountsFileBuilder;
			JSONArray accountsList;
			JSONObject currentAccount;
			String currentLine;
			if (new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + "my_accounts.txt").exists()) {
				myAccountsFileReader = new BufferedReader(new FileReader(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + "my_accounts.txt")));
				myAccountsFileBuilder = new StringBuilder();
				while ((currentLine = myAccountsFileReader.readLine()) != null) {
					myAccountsFileBuilder.append(currentLine);
				}
				myAccountsFileReader.close();
				accountsList = new JSONArray(myAccountsFileBuilder.toString());
				for (int index = 0; index < accountsList.length(); index++) {
					currentAccount = accountsList.optJSONObject(index);
					clientID = currentAccount.optString("client_id").toString();
					countryCode = currentAccount.optString("country_code").toString();
					userID = currentAccount.optString("user_id").toString();
					clientUrl = currentAccount.optString("client_url").toString();
					File baseDirectory = Environment.getExternalStorageDirectory();
					File databaseDir = new File(baseDirectory.getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/database");
					File processFileDir = new File(mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/database/process/");
					if (databaseDir.exists()) {
						String attachmentsPath = baseDirectory.getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/database/attachments";
						String queuesPath = baseDirectory.getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/database/queue";
						if (new File(attachmentsPath).exists()) {
							File[] attachmentsFiles = new File(attachmentsPath).listFiles();
							if (attachmentsFiles != null) {
								for (int attachIndex = 0; attachIndex < attachmentsFiles.length; attachIndex++) {
									if (attachmentsFiles[attachIndex].length() == 0) {
										breakIndication = "true";
										break;
									}
									String[] fileName = attachmentsFiles[attachIndex].toString().split("/");
									String attachURL = clientUrl + "/common/components/QueueManager/QueueUpload.aspx?file_path=attachments&client_id=" + clientID + "&country_code=" + countryCode + "&user_id=" + userID + "&file_name=" + fileName[fileName.length - 1].toString();
									statusIndication = sendFilesToServer(attachmentsFiles[attachIndex].toString(), fileName[fileName.length - 1].toString(), attachURL);
									if (statusIndication.equals("true")) {
										breakIndication = "true";
										break;
									}
								}
							}
						}
						if (statusIndication.equals("false")) {
							if (new File(queuesPath).exists()) {
								File[] queueFiles = new File(queuesPath).listFiles();
								if (queueFiles != null) {
									for (int queueIndex = 0; queueIndex < queueFiles.length; queueIndex++) {
										if (queueFiles[queueIndex].length() == 0) {
											breakIndication = "true";
											break;
										}
										String[] fileName = queueFiles[queueIndex].toString().split("/");
										String queueURL = clientUrl + "/common/components/QueueManager/QueueUpload.aspx?file_path=queue&client_id=" + clientID + "&country_code=" + countryCode + "&user_id=" + userID + "&file_name=" + fileName[fileName.length - 1].toString();
										sendFilesToServer(queueFiles[queueIndex].toString(), fileName[fileName.length - 1].toString(), queueURL);
									}
								}
							}
						}
					} else {
						System.out.println("No database directory");
					}
				}
				if (breakIndication.equals("false")) {
					callbackContext.success();
				} else {
					callbackContext.error("failure");
				}
			} else {
				System.out.println("No my accounts file");
			}
		} catch (Exception e) {
			System.out.println("out exception : " + e.getMessage());
		}
	}

	/*GETTING A FILEPATH OF API LEVEL 19 AND ABOVE */
	public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
		Cursor cursor = null;
		final String column = "_data";
		final String[] projection = {
				column
		};

		try {
			cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
			if (cursor != null && cursor.moveToFirst()) {
				final int column_index = cursor.getColumnIndexOrThrow(column);
				return cursor.getString(column_index);
			}
		} finally {
			if (cursor != null)
				cursor.close();
		}
		return null;
	}

	@TargetApi(Build.VERSION_CODES.KITKAT)
	public static String getPathToNonPrimaryVolume(Context context, String tag) {
		File[] volumes = context.getExternalCacheDirs();
		if (volumes != null) {
			for (File volume : volumes) {
				if (volume != null) {
					String path = volume.getAbsolutePath();
					if (path != null) {
						int index = path.indexOf(tag);
						if (index != -1) {
							return path.substring(0, index) + tag;
						}
					}

				}
			}
		}
		return null;
	}

	public String refreshTimeProfile(String date, String hour, String minute) {
		try {
			String serverResponseDate, deviceDate, serverDate;
			Date serverDateObj, todayDateobj;
			SimpleDateFormat serverDateformat, deviceDateFormat, serverDateString;
			BufferedWriter writerObj;
			serverResponseDate = date + " " + hour + ":" + minute + ":00";
			serverDateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale);
			serverDateObj = serverDateformat.parse(serverResponseDate);
			serverDateString = new SimpleDateFormat("yyyy,MM,dd,HH,mm,ss", locale);
			serverDate = serverDateString.format(serverDateObj);
			deviceDateFormat = new SimpleDateFormat("yyyy,MM,dd,HH,mm,ss", locale);
			todayDateobj = new Date();
			deviceDate = deviceDateFormat.format(todayDateobj);
			JSONObject dateObj = new JSONObject();
			dateObj.put("serverDate", serverDate);
			dateObj.put("initServerDate", serverDate);
			dateObj.put("initDeviceDate", deviceDate);
			writerObj = new BufferedWriter(new FileWriter(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/time_profile.txt")));
			writerObj.write(dateObj.toString());
			writerObj.flush();
			writerObj.close();
			return "true";
		} catch (Exception e) {
			return "false";
		}
	}

	public void getNewDate(CallbackContext callbackContext) {
		String currentLine;
		StringBuilder timeObj = new StringBuilder();
		try {
			Date mobileDate = new Date();
			File baseDirectory = Environment.getExternalStorageDirectory();
			BufferedReader readerObj = new BufferedReader(new FileReader(new File(baseDirectory, "/" + mInterfaceUtil.packageName + "/time_profile.txt")));
			while ((currentLine = readerObj.readLine()) != null) {
				timeObj.append(currentLine);
			}
			readerObj.close();
			JSONObject serverDateObj = new JSONObject(timeObj.toString());
			String serverTimeObj = serverDateObj.optString("serverDate").toString();
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy,MM,dd,HH,mm,ss", locale);
			Date serverDate = simpleDateFormat.parse(serverTimeObj);
			long timeDiff = mobileDate.getTime() - serverDate.getTime();
			serverDate.setTime(serverDate.getTime() + timeDiff);
			SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy,MM,dd,HH,mm,ss", locale);
			String serverDate1 = simpleDateFormat1.format(serverDate);
			callbackContext.success(serverDate1);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void logData(String fileName, String data) {
		File appDirectory;
		FileWriter fileWriterObj;

		try {

			/* CHECKING THE DIRECTORY EXISTS OR NOT AND CREATING THE DIRECTORY */
			appDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + fileName.substring(0, fileName.lastIndexOf("/")));
			if (!appDirectory.exists()) {
				appDirectory.mkdirs();
			}


			/* WRITING THE DATA TO THE FILE */
			fileWriterObj = new FileWriter(new File(appDirectory, fileName.substring(fileName.lastIndexOf("/") + 1)), true);
			fileWriterObj.write(data);
			fileWriterObj.flush();
			fileWriterObj.close();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void deleteFilesFromDirectory() {
		File dir = new File(Environment.getExternalStorageDirectory() + "/" + mInterfaceUtil.packageName + "/" + "images");
		if (dir.isDirectory()) {
			if (dir.exists()) {
				String[] children = dir.list();
				for (int i = 0; i < children.length; i++) {
					new File(dir, children[i]).delete();
				}
			}
		}
	}

	public String sendFilesToServer(String filePath, String fileName, String requestURL) {
		String statusIndication = "false";
		try {
			FileInputStream fileInputStream;
			HttpURLConnection urlConObj;
			URL requestPath;
			int bytesRead,
					bytesAvailable,
					bufferSize;
			byte[] buffer;
			int maxBufferSize = 1 * 1024 * 1024;
			DataOutputStream dos;
			String lineEnd = "\r\n";
			String twoHyphens = "--";
			String boundary = "*****";
			StringBuilder serverResponseObj;
			BufferedReader readerObj;
			String currentLine,
					receiveData = "";
			if (new File(filePath).exists()) {
				if (new File(filePath).exists()) {
					fileInputStream = new FileInputStream(new File(filePath));
					requestPath = new URL((requestURL).replaceAll(" ", "%20"));
					urlConObj = (HttpURLConnection) requestPath.openConnection();
					urlConObj.setDoInput(true); // Allow Inputs
					urlConObj.setDoOutput(true); // Allow Outputs
					urlConObj.setUseCaches(false); // Don't use a Cached Copy
					urlConObj.setRequestMethod("POST");
					urlConObj.setRequestProperty("Connection", "Keep-Alive");
					urlConObj.setRequestProperty("ENCTYPE", "multipart/form-data");
					urlConObj.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
					urlConObj.setRequestProperty("uploaded_file", fileName);

					dos = new DataOutputStream(urlConObj.getOutputStream());
					dos.writeBytes(twoHyphens + boundary + lineEnd);
					dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\""
							+ fileName + "\"" + lineEnd);
					dos.writeBytes(lineEnd);
					// create a buffer of  maximum size
					bytesAvailable = fileInputStream.available();

					bufferSize = Math.min(bytesAvailable, maxBufferSize);
					buffer = new byte[bufferSize];

					// read file and write it into form...
					bytesRead = fileInputStream.read(buffer, 0, bufferSize);
					while (bytesRead > 0) {
						dos.write(buffer, 0, bufferSize);
						bytesAvailable = fileInputStream.available();
						bufferSize = Math.min(bytesAvailable, maxBufferSize);
						bytesRead = fileInputStream.read(buffer, 0, bufferSize);

					}
					// send multipart form data necesssary after file data...
					dos.writeBytes(lineEnd);
					dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
					urlConObj.getResponseCode();
					//close the streams //
					fileInputStream.close();
					dos.flush();
					dos.close();
					readerObj = new BufferedReader(new InputStreamReader(urlConObj.getInputStream()));
					currentLine = readerObj.readLine();
					readerObj.close();
					receiveData = currentLine.toString();
					urlConObj.disconnect();
					if (receiveData.equals("true")) {
						new File(filePath).delete();
					} else {
						statusIndication = "true";
					}
					urlConObj.disconnect();
				}
			}
		} catch (Exception e) {
			statusIndication = "true";
		}
		return statusIndication;
	}

	public void readFile(JSONArray args, CallbackContext callbackContext) {
		String str = "";
		File baseDirectory = Environment.getExternalStorageDirectory();
		try {
			File filePath = new File(baseDirectory.getAbsolutePath() + "/" + args.getJSONObject(0).optString("filePath"));
			if (filePath.exists()) {
				BufferedReader readerObj = new BufferedReader(new FileReader(new File(Environment.getExternalStorageDirectory(), "/" + args.getJSONObject(0).optString("filePath"))));
				String line = readerObj.readLine();
				while (line != null) {
					str += line;
					line = readerObj.readLine();
				}
				readerObj.close();
				callbackContext.success(str);
			} else {
				callbackContext.error("There is no file at the given path..");
			}
		} catch (Exception e) {
			callbackContext.error(e.getMessage());
		}
	}

	public void deleteFile(JSONArray args, CallbackContext callbackContext) {
		File baseDirectory = Environment.getExternalStorageDirectory();
		try {
			File filePath = new File(baseDirectory.getAbsolutePath() + "/" + args.getJSONObject(0).optString("filePath"));
			if (filePath.exists()) {
				filePath.delete();
				callbackContext.success();
			} else {
				callbackContext.error("File not deleted..");
			}
		} catch (Exception e) {
			callbackContext.error(e.getMessage());
		}
	}

	public void createFile(JSONArray args, CallbackContext callbackContext) {
		File appDirectory;
		FileWriter fileWriterObj;
		try {
			String fileName = args.getJSONObject(0).optString("filePath");
			String data = args.getJSONObject(0).optString("data");
			/* CHECKING THE DIRECTORY EXISTS OR NOT AND CREATING THE DIRECTORY */
			String aaaa = fileName.substring(0, fileName.lastIndexOf("/"));
			appDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + fileName.substring(0, fileName.lastIndexOf("/")));
			if (!appDirectory.exists()) {
				appDirectory.mkdirs();
			}
			/* WRITING THE DATA TO THE FILE */
			String bbbb = fileName.substring(fileName.lastIndexOf("/") + 1);
			fileWriterObj = new FileWriter(new File(appDirectory, fileName.substring(fileName.lastIndexOf("/") + 1)));
			fileWriterObj.write(data);
			fileWriterObj.flush();
			fileWriterObj.close();
			callbackContext.success();
		} catch (Exception e) {
			callbackContext.error(e.getMessage());
		}
	}

	public void validateFile(JSONArray args, CallbackContext callbackContext) {
		File baseDirectory = Environment.getExternalStorageDirectory();
		try {
			File filePath = new File(baseDirectory.getAbsolutePath() + "/" + args.getJSONObject(0).optString("filePath"));
			boolean sss = filePath.exists() ? true : false;
			callbackContext.success(sss ? "true" : "false");
		} catch (Exception e) {
			callbackContext.error(e.getMessage());
		}
	}

	public void createDirectory(JSONArray args, CallbackContext callbackContext) {
		File appDirectory;
		FileWriter fileWriterObj;
		try {
			String fileName = args.getJSONObject(0).optString("filePath");
			appDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + fileName);
			if (!appDirectory.exists()) {
				appDirectory.mkdirs();
			}
			callbackContext.success();
		} catch (Exception e) {
			callbackContext.error(e.getMessage());
		}
	}

	public void deleteDirectory(JSONArray args, CallbackContext callbackContext) {
		File appDirectory;
		FileWriter fileWriterObj;
		try {
			String fileName = args.getJSONObject(0).optString("filePath");
			appDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + fileName);
			if (!appDirectory.exists()) {
				appDirectory.delete();
			}
			callbackContext.success();
		} catch (Exception e) {
			callbackContext.error(e.getMessage());
		}
	}

	private static int BUFFER_SIZE = 6 * 1024;
	public static void unzip(String zipFile, String location, CallbackContext callbackContext) throws JSONException {
		try {
			File f = new File(location);
			if (!f.isDirectory()) {
				f.mkdirs();
			}
			ZipInputStream zin = new ZipInputStream(new FileInputStream(zipFile));
			try {
				ZipEntry ze = null;
				while ((ze = zin.getNextEntry()) != null) {
					String path = location + File.separator + ze.getName();

					if (ze.isDirectory()) {
						File unzipFile = new File(path);
						if (!unzipFile.isDirectory()) {
							unzipFile.mkdirs();
						}
					} else {
						FileOutputStream fout = new FileOutputStream(path, false);

						try {
							for (int c = zin.read(); c != -1; c = zin.read()) {
								fout.write(c);
							}
							zin.closeEntry();
						} finally {
							fout.close();
						}
					}
				}
			} finally {
				zin.close();
			}
			callbackContext.success();
		} catch (Exception e) {
			e.printStackTrace();
			callbackContext.error(e.getMessage());
		}
	}
}