package com.jasamedika.medifirst2000.controller.base;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.jasamedika.medifirst2000.base.vo.BaseModelVO;
import com.jasamedika.medifirst2000.constants.Constants;
import com.jasamedika.medifirst2000.converter.BaseConverterImpl;
import com.jasamedika.medifirst2000.core.web.WebConstants;
import com.jasamedika.medifirst2000.entities.Pegawai;
import com.jasamedika.medifirst2000.service.ActivityPegawaiService;
import com.jasamedika.medifirst2000.service.LoginUserService;
import com.jasamedika.medifirst2000.service.ModelService;
import com.jasamedika.medifirst2000.util.rest.RestUtil;
import com.jasamedika.medifirst2000.vo.ModelVO;
import com.jasamedika.medifirst2000.vo.PasienVO;
import com.jasamedika.medifirst2000.vo.PegawaiVO;

import io.socket.client.IO;

/**
 * Base Controller Class for handling messaga resource for internationalization
 * & locale
 * 
 * @author Roberto
 */
public abstract class LocaleController<V extends BaseModelVO> {

	/*
	 * messageSource bean injected for each controller for accessing message
	 * source
	 */
	@Autowired
	private ActivityPegawaiService activityPegawaiServiceImpl;

	@Autowired
	private BaseConverterImpl<PegawaiVO, Pegawai> pegawaiConverter;

	@Autowired
	private LoginUserService loginUserService;

	@Autowired
	private MessageSource messageSource;

	@SuppressWarnings("rawtypes")
	@Autowired
	private ModelService modelService;

	protected Map<String, String> mapHeaderMessage = new HashMap<String, String>();

	/*
	 * code locale
	 */
	protected String getMessage(String code, HttpServletRequest request) {
		return messageSource.getMessage(code, null, new Locale(getCoociesLanguage(request)));
	}

	protected void SaveLog(String keterangan, String group, HttpServletRequest request) {
		activityPegawaiServiceImpl.record(
				pegawaiConverter.transferModelToVO(loginUserService.getLoginUser().getPegawai(), new PegawaiVO()),
				new Date(), keterangan, group);
	}

	protected Object getItem(HttpServletRequest request, Object vo) {
		BufferedReader reader;
		String read = null;
		String resultData = "";
		Gson gson = new Gson();
		try {
			reader = new BufferedReader(new InputStreamReader(request.getInputStream()));

			while ((read = reader.readLine()) != null) {
				resultData += read;
				System.out.println(read);
			}

			gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return vo = gson.fromJson(resultData, vo.getClass());
	}

	protected Object getItem2(HttpServletRequest request, Object vo) {
		BufferedReader reader;
		String read = null;
		String resultData = "";
		Gson gson = new Gson();
		try {
			reader = new BufferedReader(new InputStreamReader(request.getInputStream()));

			while ((read = reader.readLine()) != null) {
				resultData += read;
				System.out.println(read);
			}
			GsonBuilder gsonBuilder = new GsonBuilder();
			gsonBuilder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
				@Override
				public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
						throws JsonParseException {
					if (json.getAsString() instanceof String) {
						return new Date();
					} else {
						return new Date(json.getAsJsonPrimitive().getAsLong());
					}
				}
			});
			gson = gsonBuilder.create();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return vo = gson.fromJson(resultData, vo.getClass());
	}

	@RequestMapping(value = "/lang/{lang}", method = RequestMethod.GET)
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
			@PathVariable("lang") String lang) throws Exception {

		Cookie[] cookies = request.getCookies();
		List<Cookie> cookieList = new ArrayList<Cookie>();
		if (cookies != null) {
			cookieList = Arrays.asList(cookies);
			for (Cookie cookie : cookieList) {
				if (cookie.getName().equals("lang")) {
					cookie.setValue(null);
					cookie.setMaxAge(0);
					cookie.setPath("/");
					response.addCookie(cookie);
				}
			}
		}

		if (lang.equalsIgnoreCase("en")) {
			Cookie c = new Cookie("lang", "en");
			c.setPath("/");
			c.setDomain("localhost");
			response.addCookie(c);
		} else if (lang.equalsIgnoreCase("cn")) {
			Cookie c = new Cookie("lang", "cn");
			c.setPath("/");
			c.setDomain("localhost");
			response.addCookie(c);
		} else if (lang.equalsIgnoreCase("ina")) {
			Cookie c = new Cookie("lang", "ina");
			c.setPath("/");
			c.setDomain("localhost");
			response.addCookie(c);
		}

		return true;
	}

	/*
	 * default locale ID
	 */
	protected String getMessage(String code) {
		return messageSource.getMessage(code, null, new Locale(Constants.Locale.INA));
	}

	protected void addHeaderMessage(String key, String message) {
		this.mapHeaderMessage.put(key, message);
	}

	@RequestMapping(value = "/entity-serelize/{entity}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
	public ResponseEntity<ModelVO> serializeEntity(@PathVariable("entity") String entity, HttpServletRequest request) {
		ModelVO modelDTO = modelService.getModelSerializeEntity(entity, getCoociesLanguage(request));
		return RestUtil.getJsonResponse(modelDTO, HttpStatus.OK);
	}

	public String getCoociesLanguage(HttpServletRequest request) {
		Cookie cookie[] = request.getCookies();
		Cookie cook;
		String lang = Constants.Locale.INA;
		if (cookie != null) {
			for (int i = 0; i < cookie.length; i++) {
				cook = cookie[i];
				if (cook.getName().equalsIgnoreCase("lang"))
					lang = cook.getValue();
			}
		}

		return lang;

	}

	@SuppressWarnings("rawtypes")
	protected ResponseEntity constructListPageResult(Map<String, Object> map) {

		if (map == null) {
			Map<String, String> mapHeaderMessage = new HashMap<String, String>();
			mapHeaderMessage.put(WebConstants.HttpHeaderInfo.TOTAL_PAGE_HEADER, "0");
			mapHeaderMessage.put(WebConstants.HttpHeaderInfo.TOTAL_COUNT_HEADER, "0");
			mapHeaderMessage.put(Constants.MessageInfo.ERROR_MESSAGE, "Data not found.");
			return RestUtil.getJsonResponse(null, HttpStatus.BAD_REQUEST, mapHeaderMessage);
		} else {
			@SuppressWarnings("unchecked")
			Collection<PasienVO> vos = (Collection<PasienVO>) map.get(WebConstants.PageParameter.LIST_DATA);

			Map<String, String> mapHeaderMessage = new HashMap<String, String>();
			mapHeaderMessage.put(WebConstants.HttpHeaderInfo.TOTAL_PAGE_HEADER,
					String.valueOf(map.get(WebConstants.PageParameter.TOTAL_PAGES)));
			mapHeaderMessage.put(WebConstants.HttpHeaderInfo.TOTAL_COUNT_HEADER,
					String.valueOf(map.get(WebConstants.PageParameter.TOTAL_ELEMENTS)));

			return RestUtil.getJsonResponse(vos, HttpStatus.OK, mapHeaderMessage);
		}
	}

	public String GetSettingDataFixed(String prefix) {
		return activityPegawaiServiceImpl.GetSettingDataFixed(prefix);
	}

	protected void BroadcastMessage(final String to, final Object data) {
		final io.socket.client.Socket socket;
		try {
			String url = GetSettingDataFixed("UrlSocketMessaging");
			socket = IO.socket(url);

			socket.on(io.socket.client.Socket.EVENT_CONNECT, new io.socket.emitter.Emitter.Listener() {

				@Override
				public void call(Object... args) {

					try {
						Gson gson = new Gson();
						String json = gson.toJson(data);
						JSONObject item = new JSONObject(
								"{\"to\":\"" + to + "\",\"message\":\"" + json.replace("\"", "'") + "\"}");
						socket.emit("subscribe", item);
					} catch (JSONException e) {
						e.printStackTrace();
					}
				}

			});
			socket.connect();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
	}

	protected void BroadcastMessage(final String to, final String data) {
		final io.socket.client.Socket socket;
		try {
			socket = IO.socket(GetSettingDataFixed("UrlSocketMessaging"));

			socket.on(io.socket.client.Socket.EVENT_CONNECT, new io.socket.emitter.Emitter.Listener() {

				@Override
				public void call(Object... args) {

					try {
						JSONObject item = new JSONObject("{\"to\":\"" + to + "\",\"message\":\"" + data + "\"}");
						socket.emit("subscribe", item);
					} catch (JSONException e) {
						e.printStackTrace();
					}
				}

			});
			socket.connect();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
	}

	protected void BroadcastMessageOther(final String to, final Object data) {
		final io.socket.client.Socket socket;
		try {
			String url = GetSettingDataFixed("UrlSocketMessaging");
			socket = IO.socket(url);

			socket.on(io.socket.client.Socket.EVENT_CONNECT, new io.socket.emitter.Emitter.Listener() {

				@Override
				public void call(Object... args) {
					try {
						Map<String, Object> result = new HashMap<>();
						result.put("message", data);
						result.put("to", to);

						Gson gson = new Gson();
						JSONObject item = new JSONObject(gson.toJson(result));
						socket.emit("subscribe", item);
					} catch (JSONException e) {
						e.printStackTrace();
					}
				}
			});
			socket.connect();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
	}

}
