/**
 * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of the Liferay Enterprise
 * Subscription License ("License"). You may not use this file except in
 * compliance with the License. You can obtain a copy of the License by
 * contacting Liferay, Inc. See the License for the specific language governing
 * permissions and limitations under the License, including but not limited to
 * distribution rights of the Software.
 *
 *
 *
 */

package com.liferay.portal.model.impl;

import com.liferay.portal.kernel.bean.AutoEscape;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.io.ProtectedObjectInputStream;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.Base64;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.model.Account;
import com.liferay.portal.model.CacheField;
import com.liferay.portal.model.Company;
import com.liferay.portal.model.CompanyConstants;
import com.liferay.portal.model.Group;
import com.liferay.portal.model.LayoutSet;
import com.liferay.portal.model.Shard;
import com.liferay.portal.model.User;
import com.liferay.portal.model.VirtualHost;
import com.liferay.portal.service.AccountLocalServiceUtil;
import com.liferay.portal.service.GroupLocalServiceUtil;
import com.liferay.portal.service.LayoutSetLocalServiceUtil;
import com.liferay.portal.service.ShardLocalServiceUtil;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.portal.service.VirtualHostLocalServiceUtil;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portal.util.PrefsPropsUtil;
import com.liferay.portal.util.PropsValues;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;

import java.security.Key;
import java.security.KeyRep;

import java.util.Locale;
import java.util.TimeZone;

/**
 * @author Brian Wing Shun Chan
 */
public class CompanyImpl extends CompanyBaseImpl {

	public CompanyImpl() {
	}

	@Override
	public int compareTo(Company company) {
		String webId1 = getWebId();
		String webId2 = company.getWebId();

		if (webId1.equals(PropsValues.COMPANY_DEFAULT_WEB_ID)) {
			return -1;
		}
		else if (webId2.equals(PropsValues.COMPANY_DEFAULT_WEB_ID)) {
			return 1;
		}
		else {
			return webId1.compareTo(webId2);
		}
	}

	@Override
	public Account getAccount() throws PortalException, SystemException {
		return AccountLocalServiceUtil.getAccount(
			getCompanyId(), getAccountId());
	}

	@Override
	public String getAdminName() {
		return "Administrator";
	}

	@Override
	public String getAuthType() throws SystemException {
		return PrefsPropsUtil.getString(
			getCompanyId(), PropsKeys.COMPANY_SECURITY_AUTH_TYPE,
			PropsValues.COMPANY_SECURITY_AUTH_TYPE);
	}

	@Override
	public User getDefaultUser() throws PortalException, SystemException {
		return UserLocalServiceUtil.getDefaultUser(getCompanyId());
	}

	@Override
	public String getDefaultWebId() {
		return PropsValues.COMPANY_DEFAULT_WEB_ID;
	}

	@Override
	public String getEmailAddress() {

		// Primary email address

		return "admin@" + getMx();
	}

	@Override
	public Group getGroup() throws PortalException, SystemException {
		if (getCompanyId() > CompanyConstants.SYSTEM) {
			return GroupLocalServiceUtil.getCompanyGroup(getCompanyId());
		}

		return new GroupImpl();
	}

	@Override
	public long getGroupId() throws PortalException, SystemException {
		Group group = getGroup();

		return group.getGroupId();
	}

	@Override
	public Key getKeyObj() {
		if (_keyObj == null) {
			String key = getKey();

			if (Validator.isBlank(key)) {
				return _keyObj;
			}

			try {
				ObjectInputStream ois = new CompanyKeyObjectInputStream(key);

				_keyObj = (Key)ois.readObject();
			}
			catch (Exception e) {
				_log.error(
					"Unable to deserialize " + key +
						", possible Java deserialization attack",
					e);
			}
		}

		return _keyObj;
	}

	@Override
	public Locale getLocale() throws PortalException, SystemException {
		return getDefaultUser().getLocale();
	}

	@AutoEscape
	@Override
	public String getName() throws PortalException, SystemException {
		return getAccount().getName();
	}

	@Override
	public String getPortalURL(long groupId)
		throws PortalException, SystemException {

		int portalPort = PortalUtil.getPortalPort(false);

		String portalURL = PortalUtil.getPortalURL(
			getVirtualHostname(), portalPort, false);

		if (groupId <= 0) {
			return portalURL;
		}

		Group group = GroupLocalServiceUtil.getGroup(groupId);

		if (group.hasPublicLayouts()) {
			LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
				groupId, false);

			if (Validator.isNotNull(layoutSet.getVirtualHostname())) {
				portalURL = PortalUtil.getPortalURL(
					layoutSet.getVirtualHostname(), portalPort, false);
			}
		}
		else if (group.hasPrivateLayouts()) {
			LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
				groupId, true);

			if (Validator.isNotNull(layoutSet.getVirtualHostname())) {
				portalURL = PortalUtil.getPortalURL(
					layoutSet.getVirtualHostname(), portalPort, false);
			}
		}

		return portalURL;
	}

	@Override
	public String getShardName() throws PortalException, SystemException {
		Shard shard = ShardLocalServiceUtil.getShard(
			Company.class.getName(), getCompanyId());

		return shard.getName();
	}

	@Override
	public String getShortName() throws PortalException, SystemException {
		return getName();
	}

	@Override
	public TimeZone getTimeZone() throws PortalException, SystemException {
		return getDefaultUser().getTimeZone();
	}

	@Override
	public String getVirtualHostname() {
		if (_virtualHostname != null) {
			return _virtualHostname;
		}

		VirtualHost virtualHost = null;

		try {
			virtualHost = VirtualHostLocalServiceUtil.fetchVirtualHost(
				getCompanyId(), 0);
		}
		catch (Exception e) {
		}

		if (virtualHost == null) {
			return StringPool.BLANK;
		}

		_virtualHostname = virtualHost.getHostname();

		return _virtualHostname;
	}

	@Override
	public boolean hasCompanyMx(String emailAddress) throws SystemException {
		emailAddress = StringUtil.toLowerCase(emailAddress.trim());

		int pos = emailAddress.indexOf(CharPool.AT);

		if (pos == -1) {
			return false;
		}

		String mx = emailAddress.substring(pos + 1);

		if (mx.equals(getMx())) {
			return true;
		}

		String[] mailHostNames = PrefsPropsUtil.getStringArray(
			getCompanyId(), PropsKeys.ADMIN_MAIL_HOST_NAMES,
			StringPool.NEW_LINE, PropsValues.ADMIN_MAIL_HOST_NAMES);

		for (int i = 0; i < mailHostNames.length; i++) {
			if (StringUtil.equalsIgnoreCase(mx, mailHostNames[i])) {
				return true;
			}
		}

		return false;
	}

	@Override
	public boolean isAutoLogin() throws SystemException {
		return PrefsPropsUtil.getBoolean(
			getCompanyId(), PropsKeys.COMPANY_SECURITY_AUTO_LOGIN,
			PropsValues.COMPANY_SECURITY_AUTO_LOGIN);
	}

	@Override
	public boolean isSendPassword() throws SystemException {
		return PrefsPropsUtil.getBoolean(
			getCompanyId(), PropsKeys.COMPANY_SECURITY_SEND_PASSWORD,
			PropsValues.COMPANY_SECURITY_SEND_PASSWORD);
	}

	@Override
	public boolean isSendPasswordResetLink() throws SystemException {
		return PrefsPropsUtil.getBoolean(
			getCompanyId(), PropsKeys.COMPANY_SECURITY_SEND_PASSWORD_RESET_LINK,
			PropsValues.COMPANY_SECURITY_SEND_PASSWORD_RESET_LINK);
	}

	@Override
	public boolean isSiteLogo() throws SystemException {
		return PrefsPropsUtil.getBoolean(
			getCompanyId(), PropsKeys.COMPANY_SECURITY_SITE_LOGO,
			PropsValues.COMPANY_SECURITY_SITE_LOGO);
	}

	@Override
	public boolean isStrangers() throws SystemException {
		return PrefsPropsUtil.getBoolean(
			getCompanyId(), PropsKeys.COMPANY_SECURITY_STRANGERS,
			PropsValues.COMPANY_SECURITY_STRANGERS);
	}

	@Override
	public boolean isStrangersVerify() throws SystemException {
		return PrefsPropsUtil.getBoolean(
			getCompanyId(), PropsKeys.COMPANY_SECURITY_STRANGERS_VERIFY,
			PropsValues.COMPANY_SECURITY_STRANGERS_VERIFY);
	}

	@Override
	public boolean isStrangersWithMx() throws SystemException {
		return PrefsPropsUtil.getBoolean(
			getCompanyId(), PropsKeys.COMPANY_SECURITY_STRANGERS_WITH_MX,
			PropsValues.COMPANY_SECURITY_STRANGERS_WITH_MX);
	}

	@Override
	public void setKey(String key) {
		_keyObj = null;

		super.setKey(key);
	}

	@Override
	public void setKeyObj(Key keyObj) {
		_keyObj = keyObj;
	}

	@Override
	public void setVirtualHostname(String virtualHostname) {
		_virtualHostname = virtualHostname;
	}

	@CacheField
	private Key _keyObj;

	@CacheField
	private String _virtualHostname;

	private static Log _log = LogFactoryUtil.getLog(CompanyImpl.class);

	class CompanyKeyObjectInputStream extends ProtectedObjectInputStream {

		public CompanyKeyObjectInputStream(String key) throws IOException {
			super(new ByteArrayInputStream(Base64.decode(key)));
		}

		@Override
		protected Class<?> doResolveClass(ObjectStreamClass objectStreamClass)
			throws ClassNotFoundException, IOException {

			Class streamClass = super.doResolveClass(objectStreamClass);

			if (streamClass == null) {
				return null;
			}

			if (_log.isDebugEnabled()) {
				_log.debug("Deserializating " + streamClass);
			}

			if ((streamClass.isArray() &&
				 streamClass.getComponentType().isPrimitive()) ||
				Key.class.isAssignableFrom(streamClass) ||
				KeyRep.class.isAssignableFrom(streamClass) ||
				Enum.class.isAssignableFrom(streamClass)) {

				return streamClass;
			}

			throw new InvalidClassException(
				"Rejected resolving of illegal class " +
					objectStreamClass.getName());
		}
	}

}