package fi.nls.oskari.portlet.util;

import java.util.List;
import java.util.Locale;
import java.util.UUID;

import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.Role;
import com.liferay.portal.model.RoleConstants;
import com.liferay.portal.service.RoleLocalServiceUtil;
import com.liferay.portal.service.ServiceContext;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portlet.expando.model.ExpandoBridge;
import fi.nls.oskari.control.ActionParameters;
import fi.nls.oskari.domain.GuestUser;
import fi.nls.oskari.domain.User;
import fi.nls.oskari.log.LogFactory;
import fi.nls.oskari.log.Logger;
import fi.nls.oskari.service.ServiceException;
import fi.nls.oskari.util.ConversionHelper;
import fi.nls.oskari.util.PropertyUtil;

import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static com.liferay.portal.util.PortalUtil.getHttpServletRequest;
import static com.liferay.portal.util.PortalUtil.getOriginalServletRequest;


public class LiferayUtil {

    public final static String ADDITIONAL_PORTLET_REQUEST = "portletRequest";
    public final static String ADDITIONAL_PORTLET_RESPONSE = "portletResponse";
    public final static String ADDITIONAL_THEME_DISPLAY = "ThemeDisplay";
    public static final String EXPANDO_UUID = "uuid";

    private static Logger log = LogFactory.getLogger(LiferayUtil.class);
    private static final long companyId = ConversionHelper.getLong(PropertyUtil.getOptional("oskari.default.companyId"), -1); // 10108
    private static final long systemUserId = ConversionHelper.getLong(PropertyUtil.getOptional("oskari.default.systemUserId"), -1); // 10203

    public static String addUUIDtoUser(com.liferay.portal.model.User user) {
        String uuid = null; // GUEST

        List<Role> roles;
        try {
            roles = user.getRoles();
        } catch (SystemException sysex) {
            throw new RuntimeException("Could not get Roles.", sysex);
        }
        boolean isGuest = roles.size() == 0;

        for (Role role : roles) {
            if (role.getName().equals(RoleConstants.GUEST)) {
                isGuest = true;
                break;
            }
        }

        if (!isGuest) {
            uuid = (String) user.getExpandoBridge().getAttribute(EXPANDO_UUID);
            if (uuid == null || "".equals(uuid)) {
                uuid = UUID.randomUUID().toString();
                user.getExpandoBridge().setAttribute(EXPANDO_UUID, uuid);
            }
        }
        return uuid;
    }

    public static com.liferay.portal.model.User addUser(User pUser, String password, final long[] roleIdList) throws ServiceException {
        if(systemUserId == -1) {
            throw new ServiceException("System user id not set. Please add a property 'oskari.default.systemUserId'");
        }
        if(companyId == -1) {
            throw new ServiceException("Company id not set. Please add a property 'oskari.default.companyId'");
        }
        return addUser(pUser, password, roleIdList, systemUserId, companyId);
    }

    public static com.liferay.portal.model.User addUser(User pUser, String password, final long[] roleIdList,
                                                        final long creatorId, final long companyId) throws ServiceException {

        long[] emptyLong = {};
        //long userId = CounterLocalServiceUtil.increment();
        //ServiceContext serviceContext = ServiceContextFactory.getInstance(User.class.getName(), request);
        ServiceContext serviceContext = new ServiceContext();
        try {
            com.liferay.portal.model.User lrUser = UserLocalServiceUtil.addUser(
                    creatorId /*long creatorUserId*/,
                    companyId /*long companyId */,
                    false /*boolean autoPassword*/,
                    password /*String password1*/,
                    password /*String password2*/,
                    false /*boolean autoScreenName*/,
                    pUser.getScreenname() /* String screenName*/,
                    pUser.getEmail() /*String emailAddress*/,
                    0,  // facebookId -> 0
                    "", // openId -> ""
                    new Locale("fi", "FI") /*Locale locale*/,
                    pUser.getFirstname() /*String firstName*/,
                    null /*String middleName*/,
                    pUser.getLastname() /*String lastName*/,
                    0/*int prefixId*/,
                    0 /*int suffixId*/,
                    false /*boolean male*/,
                    1 /*int birthdayMonth*/,
                    1 /*int birthdayDay*/,
                    2000 /*int birthdayYear*/,
                    null /*String jobTitle*/,
                    emptyLong, // long[] groupIds
                    emptyLong /*long[] organizationIds*/,
                    roleIdList, // long[] roleIds
                    emptyLong, // long[] userGroupIds
                    false /*boolean sendEmail*/,
                    serviceContext);

            // Add uuid for user
            final String uuid = addUUIDtoUser(lrUser);
            // Return the user
            return lrUser;
        } catch (Exception e) {
            throw new ServiceException("Couldn't create user", e);
        }
    }

    public static ActionParameters getActionParameters(final PortletRequest req, final PortletResponse resp) {

        final HttpServletRequest request = getOriginalServletRequest(getHttpServletRequest(req));
        final HttpServletResponse response = PortalUtil.getHttpServletResponse(resp);

        final ActionParameters params = new ActionParameters();
        params.setRequest(request);
        params.setResponse(response);
        //params.setLocale(req.getLocale());
        params.setUser(getOskariUser(request));

        // these are needed by some liferay depended functionality (document bank search etc)
        final ThemeDisplay td = ((ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY));
        params.setLocale(new Locale(td.getLocale().getLanguage()));
        params.putAdditionalParam(ADDITIONAL_THEME_DISPLAY,td);
        params.putAdditionalParam(ADDITIONAL_PORTLET_REQUEST, req);
        params.putAdditionalParam(ADDITIONAL_PORTLET_RESPONSE, resp);

        return params;
    }

    public static User getOskariUser(final PortletRequest request) {
        final HttpServletRequest req = getOriginalServletRequest(getHttpServletRequest(request));
        return getOskariUser(req);
    }
    public static User getOskariUser(final HttpServletRequest request) {
        final ThemeDisplay td = ((ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY));
        return getOskariUser(td.getUser());
    }

    public static User getOskariUser(final com.liferay.portal.model.User lruser) {
        final User user = lruser.isDefaultUser() ? new GuestUser() : new User();

        try {
            user.setId(lruser.getUserId());
            user.setFirstname(lruser.getFirstName());
            user.setLastname(lruser.getLastName());
            user.setScreenname(lruser.getScreenName());
            user.setEmail(lruser.getLogin());

            // uuid
            final ExpandoBridge userEB = lruser.getExpandoBridge();
            String userUuid = (String) userEB.getAttribute(LiferayUtil.EXPANDO_UUID);
            if (userUuid == null || "".equals(userUuid)) {
                LiferayUtil.addUUIDtoUser(lruser);
                userUuid = (String) userEB.getAttribute(LiferayUtil.EXPANDO_UUID);
            }
            user.setUuid(userUuid);

            // populate roles
            try {
                final List<Role> roles = RoleLocalServiceUtil.getUserRoles(user.getId());
                for (Role r : roles) {
                    user.addRole(r.getRoleId(), r.getName());
                }
            } catch (SystemException ignored) {
                log.error("Couldn't get roles for user", user);
            }
        } catch (Exception e) {
            // TODO: handle error
            throw new RuntimeException("Could not get user");
        }
        return user;
    }
}
