package com.wisedu.mooc.app.log.web;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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

import com.wisedu.mooc.app.log.bo.LogUserVisit;
import com.wisedu.mooc.app.log.bo.LogUserVisitPos;
import com.wisedu.mooc.app.log.service.LogUserVisitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import sun.misc.BASE64Decoder;

import com.wisedu.coeus.core.bo.LoginUser;
import com.wisedu.coeus.core.security.LoginCheck;
import com.wisedu.coeus.debug.Logger;
import com.wisedu.coeus.debug.LoggerFactory;
import com.wisedu.coeus.util.IPAddressUtils;
import com.wisedu.coeus.util.Strings;
import com.wisedu.coeus.web.LoginContext;
import com.wisedu.mooc.app.log.bo.LogStudy;
import com.wisedu.mooc.app.log.bo.LogStudyPos;
import com.wisedu.mooc.app.log.service.LogStudyService;
import com.wisedu.mooc.app.user.bo.UserInfo;


@Controller("logController")
@RequestMapping("/log")
public class LogController {

    Logger LOGGER = LoggerFactory.getLogger(LogController.class);

    @Autowired
    private LogStudyService logStudyService;

    @Autowired
    private LogUserVisitService logUserVisitService;

    /**
     * 学习行为收集
     * @param model
     * @param request
     * @param response
     * @return
     */
    @LoginCheck("false")
    @RequestMapping(value = "/study", method = RequestMethod.GET)
    public String insertLog(Model model, HttpServletRequest request, HttpServletResponse response) {
        String itemId = Strings.trimToNull(request.getParameter("ii"));//课件id
        String visitKey = Strings.trimToNull(request.getParameter("vk"));
        String visitSession = Strings.trimToNull(request.getParameter("vs"));
        String formal = Strings.trimToNull(request.getParameter("fm"))==null?"1":Strings.trimToNull(request.getParameter("fm"));

        if (itemId == null || visitKey == null || visitSession == null) {
            // 无效请求
            response.setStatus(400);
            return null;
        }

        String userAgent = Strings.trimToNull(request.getParameter("ua"));
        if (userAgent == null) {
            userAgent = request.getHeader("User-Agent");
        } else {
            BASE64Decoder decoder = new BASE64Decoder();
            try {
                userAgent = new String(decoder.decodeBuffer(userAgent), "utf-8");
            } catch (Exception e) {
                userAgent = "Unknown";
            }
        }
        //收集系统及浏览器信息
        String displaySize = Strings.trimToEmpty(request.getParameter("ds"));
        String displayColor = Strings.trimToEmpty(request.getParameter("dc"));
        String cookieSupported = Strings.trimToEmpty(request.getParameter("cs"));
        String jsSupported = Strings.trimToEmpty(request.getParameter("js"));
        String flashVer = Strings.trimToEmpty(request.getParameter("fv"));
        String flashSupported = flashVer.length() > 0 ? "1" : "0";

        Map<String, String> clientMap = parseUserAgent(userAgent);
        String osName = Strings.trimToEmpty(clientMap.get("os"));
        String osVer = Strings.trimToEmpty(clientMap.get("ov"));
        String browserName = Strings.trimToEmpty(clientMap.get("bn"));
        String browserVer = Strings.trimToEmpty(clientMap.get("bv"));

        String lang = Strings.trimToNull(request.getParameter("ln"));
        String refererUrl = Strings.trimToEmpty(request.getParameter("ru"));

        String startPos = Strings.trimToNull(request.getParameter("sp"));
        String actionType = Strings.trimToNull(request.getParameter("at"));

        if (startPos == null) startPos = "0";
        if (actionType == null) actionType = "0";
        if (lang == null) {
            lang = request.getLocale().toString();
        }

        LoginUser loginUser = null;
        try {
            loginUser = LoginContext.getLoginUser();
        } catch (Exception e) {
        }

        if (loginUser == null) {
            // 拒绝访问
            response.setStatus(403);
            return null;
        }

        if (loginUser.getGuest()) {
            // 拒绝访问
            response.setStatus(403);
            return null;
        }

        String ipAddress = IPAddressUtils.getClientIP(request);
        String country = "";
        String province = "";
        String city = "";

        //解析ip，获取地理信息
        if (!Strings.isEmpty(ipAddress) && !ipAddress.startsWith("127.")) {
            Map<String, String> locMap = IPAddressUtils.parse(ipAddress);
            country = locMap.get("country");
            province = locMap.get("province");
            city = locMap.get("city");
        }

        if (Strings.isEmpty(country)) country = "Unknown";
        if (Strings.isEmpty(province)) province = "Unknown";
        if (Strings.isEmpty(city)) city = "Unknown";

        Calendar calendar = Calendar.getInstance();

        UserInfo userInfo = LoginContext.getLoginUser().getUserInfo();
        LogStudy logStudy = new LogStudy();
        logStudy.setItemId(Long.parseLong(itemId));
        logStudy.setUserId(userInfo.getUserId());

        logStudy.setVisitKey(visitKey);
        logStudy.setVisitSession(visitSession);
        logStudy.setVisitDate(calendar.getTime());
        logStudy.setVisitTime(calendar.getTime().getTime());
        logStudy.setVisitYear(calendar.get(Calendar.YEAR));
        logStudy.setVisitMonth(calendar.get(Calendar.MONTH) + 1);
        logStudy.setVisitDay(calendar.get(Calendar.DAY_OF_MONTH));

        logStudy.setIpAddress(ipAddress);
        logStudy.setCountry(country);
        logStudy.setProvince(province);
        logStudy.setCity(city);

        logStudy.setUserAgent(userAgent);
        logStudy.setOsName(osName);
        logStudy.setOsVer(osVer);
        logStudy.setDisplaySize(displaySize);
        logStudy.setDisplayColor(displayColor);
        logStudy.setBrowserName(browserName);
        logStudy.setBrowserVer(browserVer);
        logStudy.setCookieSupported(cookieSupported);
        logStudy.setJsSupported(jsSupported);
        logStudy.setFlashSupported(flashSupported);
        logStudy.setFlashVer(flashVer);
        logStudy.setLang(lang);
        logStudy.setRefererUrl(refererUrl);
        logStudy.setFormalFlag(Strings.getInteger(formal));

        LogStudyPos logStudyPos = new LogStudyPos();
        Long pos = Math.round(Double.parseDouble(startPos));

        logStudyPos.setVisitPos(pos.intValue());

        logStudyPos.setVisitTime(calendar.getTime().getTime());
        logStudyPos.setVisitDate(calendar.getTime());
        logStudyPos.setActionType(Integer.parseInt(actionType));

        logStudyService.insertLog(logStudy, logStudyPos);

        if (Strings.isNotEmpty(request.getParameter("callback"))) {
            try {
                response.setContentType("application/x-javascript");
                response.getWriter().write(request.getParameter("callback").concat("('')"));
            } catch (Exception e) {

            }
        }

        return null;
    }


    @LoginCheck("false")
    @RequestMapping(value = "/userVisit", method = RequestMethod.GET)
    public String insertUserVisitLog(Model model, HttpServletRequest request, HttpServletResponse response) {
        String visitKey = Strings.trimToNull(request.getParameter("vk"));
        String visitSession = request.getSession().getId();

        if (visitKey == null || visitSession == null) {
            // 无效请求
            response.setStatus(200);
            return null;
        }

        String userAgent = Strings.trimToNull(request.getParameter("ua"));
        if (userAgent == null) {
            userAgent = request.getHeader("User-Agent");
        } else {
            BASE64Decoder decoder = new BASE64Decoder();
            try {
                userAgent = new String(decoder.decodeBuffer(userAgent), "utf-8");
            } catch (Exception e) {
                userAgent = "Unknown";
            }
        }

        String displaySize = Strings.trimToEmpty(request.getParameter("ds"));
        String displayColor = Strings.trimToEmpty(request.getParameter("dc"));
        String cookieSupported = Strings.trimToEmpty(request.getParameter("cs"));
        String jsSupported = Strings.trimToEmpty(request.getParameter("js"));
        String flashVer = Strings.trimToEmpty(request.getParameter("fv"));
        String flashSupported = flashVer.length() > 0 ? "1" : "0";

        Map<String, String> clientMap = parseUserAgent(userAgent);
        String osName = Strings.trimToEmpty(clientMap.get("os"));
        String osVer = Strings.trimToEmpty(clientMap.get("ov"));
        String browserName = Strings.trimToEmpty(clientMap.get("bn"));
        String browserVer = Strings.trimToEmpty(clientMap.get("bv"));

        String lang = Strings.trimToNull(request.getParameter("ln"));
        String visitUrl = Strings.trimToEmpty(request.getParameter("vu"));

        if (lang == null) {
            lang = request.getLocale().toString();
        }

        LoginUser loginUser = null;
        try {
            loginUser = LoginContext.getLoginUser();
        } catch (Exception e) {
        }

        if (loginUser == null) {
            // 拒绝访问
            response.setStatus(200);
            return null;
        }

        if (loginUser.getGuest()) {
            // 拒绝访问
            response.setStatus(200);
            return null;
        }

        //获取上一次使用的url
        String refererUrl = Strings.getString(LoginContext.getAttribute("refererUrl"));
        //将当前url设置为上次url 以便下次获取
        LoginContext.setAttribute("refererUrl", visitUrl);


        String ipAddress = IPAddressUtils.getClientIP(request);
        String country = "";
        String province = "";
        String city = "";

        if (!Strings.isEmpty(ipAddress) && !ipAddress.startsWith("127.")) {
            Map<String, String> locMap = IPAddressUtils.parse(ipAddress);
            country = locMap.get("country");
            province = locMap.get("province");
            city = locMap.get("city");
        }

        if (Strings.isEmpty(country)) country = "Unknown";
        if (Strings.isEmpty(province)) province = "Unknown";
        if (Strings.isEmpty(city)) city = "Unknown";

        Calendar calendar = Calendar.getInstance();

        UserInfo userInfo = LoginContext.getLoginUser().getUserInfo();
        Long schoolId = 1L;
        LogUserVisit logUserVisit = new LogUserVisit();
        logUserVisit.setSchoolId(schoolId);
        logUserVisit.setCoeusUserId(loginUser.getUserInfo().getUserId());

        logUserVisit.setVisitKey(visitKey);
        logUserVisit.setVisitSession(visitSession);
        logUserVisit.setVisitDate(calendar.getTime());
        logUserVisit.setVisitTime(calendar.getTime().getTime());
        logUserVisit.setVisitYear(calendar.get(Calendar.YEAR));
        logUserVisit.setVisitMonth(calendar.get(Calendar.MONTH) + 1);
        logUserVisit.setVisitDay(calendar.get(Calendar.DAY_OF_MONTH));

        logUserVisit.setIpAddress(ipAddress);
        logUserVisit.setCountry(country);
        logUserVisit.setProvince(province);
        logUserVisit.setCity(city);

        logUserVisit.setUserAgent(userAgent);
        logUserVisit.setOsName(osName);
        logUserVisit.setOsVer(osVer);
        logUserVisit.setDisplaySize(displaySize);
        logUserVisit.setDisplayColor(displayColor);
        logUserVisit.setBrowserName(browserName);
        logUserVisit.setBrowserVer(browserVer);
        logUserVisit.setCookieSupported(cookieSupported);
        logUserVisit.setJsSupported(jsSupported);
        logUserVisit.setFlashSupported(flashSupported);
        logUserVisit.setFlashVer(flashVer);
        logUserVisit.setLang(lang);
        //logUserVisit.setRefererUrl(refererUrl);
        //logUserVisit.setVisitUrl(visitUrl);

        LogUserVisitPos logUserVisitPos = new LogUserVisitPos();

        logUserVisitPos.setVisitTime(calendar.getTime().getTime());
        logUserVisitPos.setVisitDate(calendar.getTime());
        logUserVisitPos.setRefererUrl(refererUrl);
        logUserVisitPos.setVisitUrl(visitUrl);

        logUserVisitService.insertLog(logUserVisit, logUserVisitPos);

        if (Strings.isNotEmpty(request.getParameter("callback"))) {
            try {
                response.setContentType("application/x-javascript");
                response.getWriter().write(request.getParameter("callback").concat("('')"));
            } catch (Exception e) {

            }
        }

        return null;
    }

    /**
     * 从用户串中获取浏览器信息
     *
     * @param userAgent
     * @return
     */
    private Map<String, String> getBrowser(String userAgent) {
        Map<String, String> map = new HashMap<String, String>();

        Pattern pattern;
        Matcher matcher;

        pattern = Pattern.compile("Opera\\/9\\.80.+Version\\/([\\d\\.]+)", Pattern.CASE_INSENSITIVE);
        matcher = pattern.matcher(userAgent);

        if (matcher.find()) {
            map.put("bn", "Oprea");
            map.put("bv", matcher.group(1));
            return map;
        }

        pattern = Pattern.compile("Maxthon[ \\/]?([\\d\\.]*)", Pattern.CASE_INSENSITIVE);
        matcher = pattern.matcher(userAgent);
        if (matcher.find()) {
            map.put("bn", "Maxthon");
            map.put("bv", matcher.group(1));
            return map;
        }

        pattern = Pattern.compile("(OPR|Opera)[ \\/]([\\d\\.]+)", Pattern.CASE_INSENSITIVE);
        matcher = pattern.matcher(userAgent);
        if (matcher.find()) {
            map.put("bn", "Oprea");
            map.put("bv", matcher.group(2));
            return map;
        }

        pattern = Pattern.compile("Firefox[ \\/]([\\d\\.]+)", Pattern.CASE_INSENSITIVE);
        matcher = pattern.matcher(userAgent);
        if (matcher.find()) {
            map.put("bn", "Firefox");
            map.put("bv", matcher.group(1));
            return map;
        }

        pattern = Pattern.compile("Chrome[ \\/]([\\d\\.]+)", Pattern.CASE_INSENSITIVE);
        matcher = pattern.matcher(userAgent);
        if (matcher.find()) {
            map.put("bn", "Chrome");
            map.put("bv", matcher.group(1));
            return map;
        }

        pattern = Pattern.compile("Chrome[ \\/]([\\d\\.]+)", Pattern.CASE_INSENSITIVE);
        matcher = pattern.matcher(userAgent);
        if (matcher.find()) {
            map.put("bn", "Chrome");
            map.put("bv", matcher.group(1));
            return map;
        }

        pattern = Pattern.compile("AppleWebKit\\/[\\d\\.]+.+Version\\/([\\d\\.]+).*Safari", Pattern.CASE_INSENSITIVE);
        matcher = pattern.matcher(userAgent);

        if (matcher.find()) {
            map.put("bn", "Safari");
            map.put("bv", matcher.group(1));
            return map;
        }

        pattern = Pattern.compile("Trident\\/[\\d\\.]+.+rv:([\\d\\.]+).*like Gecko", Pattern.CASE_INSENSITIVE);
        matcher = pattern.matcher(userAgent);

        if (matcher.find()) {
            map.put("bn", "IE");
            map.put("bv", matcher.group(1));
            return map;
        }

        pattern = Pattern.compile("MSIE[ \\/]([\\d\\.]+)", Pattern.CASE_INSENSITIVE);
        matcher = pattern.matcher(userAgent);
        if (matcher.find()) {
            map.put("bn", "IE");
            map.put("bv", matcher.group(1));
            return map;
        }

        map.put("bn", "Unknown");
        map.put("bv", "");

        return map;
    }

    /**
     * 从用户串中获取操作系统系统
     *
     * @param userAgent
     * @return
     */
    private Map<String, String> getSystem(String userAgent) {
        Map<String, String> map = new HashMap<String, String>();

        Pattern pattern;
        Matcher matcher;

        pattern = Pattern.compile("(Windows NT|Android) ([0-9\\.]+)");
        matcher = pattern.matcher(userAgent);
        String osName = "";
        String osVer = "";

        if (matcher.find()) {
            osName = matcher.group(1);
            osVer = matcher.group(2);
            if ("Windows NT".equals(osName)) {
                osName = "Windows";
                if ("5.0".equals(osVer)) {
                    osVer = "2000";
                } else if ("5.1".equals(osVer)) {
                    osVer = "XP";
                } else if ("5.2".equals(osVer)) {
                    osVer = "2003";
                } else if ("6.0".equals(osVer)) {
                    osVer = "Vista";
                } else if ("6.1".equals(osVer)) {
                    osVer = "7";
                } else if ("6.2".equals(osVer)) {
                    osVer = "8";
                } else if ("6.3".equals(osVer)) {
                    osVer = "8.1";
                } else {
                    osVer = "Unknown";
                }
            }
            map.put("os", osName);
            map.put("ov", osVer);
            return map;
        }

        map.put("os", "Unknown");
        map.put("ov", "");

        return map;
    }

    /**
     * 解析用户串
     *
     * @param userAgent
     * @return
     */
    private Map<String, String> parseUserAgent(String userAgent) {
        Map<String, String> map = new HashMap<String, String>();

        map.putAll(getBrowser(userAgent));
        map.putAll(getSystem(userAgent));

        return map;
    }

}
