/**
 * Copyright (c) 2000-present 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.layout.internal.search.util;

import com.liferay.fragment.constants.FragmentEntryLinkConstants;
import com.liferay.petra.string.StringBundler;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.Company;
import com.liferay.portal.kernel.model.Layout;
import com.liferay.portal.kernel.model.VirtualHost;
import com.liferay.portal.kernel.service.CompanyLocalService;
import com.liferay.portal.kernel.service.VirtualHostLocalService;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.CookieKeys;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.Http;
import com.liferay.portal.kernel.util.HttpUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.Portal;

import java.net.InetAddress;

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

import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.PropsUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.util.PropsValues;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.util.EntityUtils;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

/**
 * @author Pavel Savinov
 */
@Component(immediate = true, service = LayoutCrawler.class)
public class LayoutCrawler {

	public String getLayoutContent(Layout layout, Locale locale) {
		return _getLayoutContent(layout, locale);
	}

	private String _getLayoutContent(Layout layout, Locale locale) {
		HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();

		HttpClient httpClient = httpClientBuilder.setUserAgent(
			_USER_AGENT
		).build();

		try {
			InetAddress inetAddress = _portal.getPortalServerInetAddress(false);

			ThemeDisplay themeDisplay = new ThemeDisplay();

			Company company = _companyLocalService.getCompany(
				layout.getCompanyId());

			String virtualHost = company.getVirtualHostname();

			themeDisplay.setCompany(company);

			themeDisplay.setLanguageId(LocaleUtil.toLanguageId(locale));
			themeDisplay.setLayout(layout);
			themeDisplay.setLayoutSet(layout.getLayoutSet());
			themeDisplay.setLocale(locale);
			themeDisplay.setScopeGroupId(layout.getGroupId());

			String domain = PropsUtil.get(PropsKeys.LAYOUT_CRAWLER_REQUEST_DOMAIN);
			if (Validator.isNull(domain)) {
				themeDisplay.setServerName(inetAddress.getHostName());
			} else {
				themeDisplay.setServerName(domain);
			}

			String port = PropsUtil.get(PropsKeys.LAYOUT_CRAWLER_REQUEST_PORT);
			if (Validator.isNull(port)) {
				themeDisplay.setServerPort(_portal.getPortalServerPort(false));
			} else {
				themeDisplay.setServerPort(GetterUtil.getInteger(
					PropsUtil.get(PropsKeys.LAYOUT_CRAWLER_REQUEST_PORT)));
			}

			themeDisplay.setSiteGroupId(layout.getGroupId());

			String layoutURL = _portal.getLayoutURL(layout, themeDisplay);

			if (!HttpUtil.hasProtocol(layoutURL)) {
				StringBundler sb = new StringBundler(4);

				String protocol = PropsUtil.get(PropsKeys.LAYOUT_CRAWLER_REQUEST_PROTOCOL);

				if (Validator.isNull(protocol)) {
					sb.append(Http.HTTP_WITH_SLASH);
				} else {
					sb.append(protocol);
					if (!protocol.endsWith(StringPool.SLASH)) {
						sb.append("://");
					}
				}

				if (Validator.isNull(domain)) {
					sb.append(inetAddress.getHostName());
				} else {
					sb.append(domain);
				}

				sb.append(StringPool.COLON);

				if (Validator.isNull(port)) {
					sb.append(_portal.getPortalServerPort(false));
				} else {
					sb.append(port);
				}

				String path = PropsUtil.get(PropsKeys.LAYOUT_CRAWLER_REQUEST_PATH);
				if (Validator.isNotNull(path)) {
					if (!path.startsWith(StringPool.SLASH)) {
						sb.append(StringPool.SLASH);
					}
					sb.append(path);
				}

				if (PropsValues.LOCALE_PREPEND_FRIENDLY_URL_STYLE > 0) {
					sb.append(StringPool.SLASH);
					sb.append(LocaleUtil.toW3cLanguageId(locale));
				}

				layoutURL = sb.toString() + layoutURL;
			}

			HttpGet httpGet = new HttpGet(layoutURL);

			httpGet.setHeader("Host", virtualHost);

			HttpClientContext httpClientContext = new HttpClientContext();

			CookieStore cookieStore = new BasicCookieStore();

			BasicClientCookie basicClientCookie = new BasicClientCookie(
				CookieKeys.GUEST_LANGUAGE_ID, LocaleUtil.toLanguageId(locale));

			basicClientCookie.setDomain(inetAddress.getHostName());

			cookieStore.addCookie(basicClientCookie);

			httpClientContext.setCookieStore(cookieStore);

			HttpResponse httpResponse = httpClient.execute(
				httpGet, httpClientContext);

			StatusLine statusLine = httpResponse.getStatusLine();

			if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
				return EntityUtils.toString(httpResponse.getEntity());
			}

			if (_log.isWarnEnabled()) {
				_log.warn("Unable to get layout content");
			}
		}
		catch (Exception exception) {
			if (_log.isWarnEnabled()) {
				_log.warn("Unable to get layout content", exception);
			}
		}

		return StringPool.BLANK;
	}

	private static final String _USER_AGENT = "Liferay Page Crawler";

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

	@Reference
	private CompanyLocalService _companyLocalService;

	@Reference
	private Portal _portal;

}