/**
 * Copyright (c) 2000-2017 Liferay, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of the Liferay Enterprise
 * pSubscription 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.search.buffer;

import com.liferay.portal.kernel.messaging.proxy.ProxyModeThreadLocal;
import com.liferay.portal.kernel.search.Indexer;
import com.liferay.portal.kernel.util.ClassUtil;
import com.liferay.portal.kernel.util.HashUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.model.ClassedModel;

import java.lang.reflect.Method;

/**
 * @author Michael C. Han
 */
public class IndexerRequest {

	public IndexerRequest(
		Method method, ClassedModel classedModel, Indexer indexer) {

		_method = method;
		_classedModel = classedModel;
		_indexer = indexer;

		_forceSync = ProxyModeThreadLocal.isForceSync();
		_modelClassName = classedModel.getModelClassName();
		_modelPrimaryKey = (Long)_classedModel.getPrimaryKeyObj();
	}

	public IndexerRequest(
		Method method, Indexer indexer, String modelClassName,
		Long modelPrimaryKey) {

		_method = method;
		_indexer = indexer;
		_modelClassName = modelClassName;
		_modelPrimaryKey = modelPrimaryKey;

		_classedModel = null;
		_forceSync = ProxyModeThreadLocal.isForceSync();
	}

	@Override
	public boolean equals(Object object) {
		if (this == object) {
			return true;
		}

		if (!(object instanceof IndexerRequest)) {
			return false;
		}

		IndexerRequest indexerRequest = (IndexerRequest)object;

		if (Validator.equals(_indexer, indexerRequest._indexer) &&
			(Validator.equals(_method, indexerRequest._method) ||
			 (Validator.equals(
				 _method.getName(), indexerRequest._method.getName()) &&
			  Validator.equals(
				  _modelPrimaryKey, indexerRequest._modelPrimaryKey))) &&
			Validator.equals(_modelClassName, indexerRequest._modelClassName)) {

			return true;
		}

		return false;
	}

	public void execute() throws Exception {
		boolean previousForceSync = ProxyModeThreadLocal.isForceSync();

		try {
			ProxyModeThreadLocal.setForceSync(_forceSync);

			if (_method.getParameterTypes().length == 1) {
				_method.invoke(_indexer, _classedModel);
			}
			else {
				_method.invoke(_indexer, _modelClassName, _modelPrimaryKey);
			}
		}
		finally {
			ProxyModeThreadLocal.setForceSync(previousForceSync);
		}
	}

	public String getSearchEngineId() {
		return _indexer.getSearchEngineId();
	}

	@Override
	public int hashCode() {
		int hashCode = HashUtil.hash(0, _method.getName());

		hashCode = HashUtil.hash(hashCode, _modelClassName);
		hashCode = HashUtil.hash(hashCode, _modelPrimaryKey);

		return hashCode;
	}

	@Override
	public String toString() {
		StringBundler sb = new StringBundler(13);

		sb.append("{classModel=");
		sb.append(_classedModel);
		sb.append(", forceSync=");
		sb.append(_forceSync);
		sb.append(", indexer=");
		sb.append(ClassUtil.getClassName(_indexer));
		sb.append(", method=");
		sb.append(_method);
		sb.append(", modelClassName=");
		sb.append(_modelClassName);
		sb.append(", modelPrimaryKey=");
		sb.append(_modelPrimaryKey);
		sb.append("}");

		return sb.toString();
	}

	private final ClassedModel _classedModel;
	private final boolean _forceSync;
	private final Indexer _indexer;
	private final Method _method;
	private final String _modelClassName;
	private final Long _modelPrimaryKey;

}