/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.ranger.service;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Logger;

import org.apache.commons.lang.StringUtils;
import org.apache.ranger.biz.ServiceDBStore;
import org.apache.ranger.common.AppConstants;
import org.apache.ranger.common.JSONUtil;
import org.apache.ranger.plugin.util.PasswordUtils;
import org.apache.ranger.common.PropertiesUtil;
import org.apache.ranger.common.view.VTrxLogAttr;
import org.apache.ranger.db.XXServiceVersionInfoDao;
import org.apache.ranger.entity.XXService;
import org.apache.ranger.entity.XXServiceConfigMap;
import org.apache.ranger.entity.XXServiceDef;
import org.apache.ranger.entity.XXServiceVersionInfo;
import org.apache.ranger.entity.XXTrxLog;
import org.apache.ranger.plugin.model.RangerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Service
@Scope("singleton")
public class RangerServiceService extends RangerServiceServiceBase<XXService, RangerService> {
	private static final Logger LOG = Logger.getLogger(RangerServiceService.class.getName());
	@Autowired
	JSONUtil jsonUtil;

	private String hiddenPasswordString;

	static HashMap<String, VTrxLogAttr> trxLogAttrs = new HashMap<String, VTrxLogAttr>();
	String actionCreate;
	String actionUpdate;
	String actionDelete;
	static {
		trxLogAttrs.put("name", new VTrxLogAttr("name", "Service Name", false));
		trxLogAttrs.put("description", new VTrxLogAttr("description", "Service Description", false));
		trxLogAttrs.put("isEnabled", new VTrxLogAttr("isEnabled", "Service Status", false));
		trxLogAttrs.put("configs", new VTrxLogAttr("configs", "Connection Configurations", false));
		trxLogAttrs.put("tagService", new VTrxLogAttr("tagService", "Tag Service Name", false));
	}
	
	public RangerServiceService() {
		super();
		hiddenPasswordString = PropertiesUtil.getProperty("ranger.password.hidden", "*****");
		actionCreate = "create";
		actionUpdate = "update";
		actionDelete = "delete";
	}

	@Override
	protected XXService mapViewToEntityBean(RangerService vObj, XXService xObj, int OPERATION_CONTEXT) {
		return super.mapViewToEntityBean(vObj, xObj, OPERATION_CONTEXT);
	}

	@Override
	protected RangerService mapEntityToViewBean(RangerService vObj, XXService xObj) {
		return super.mapEntityToViewBean(vObj, xObj);
	}
	
	@Override
	protected void validateForCreate(RangerService vObj) {
		// TODO Auto-generated method stub
		
	}

	@Override
	protected void validateForUpdate(RangerService vService, XXService xService) {
		
	}
	
	@Override
	protected RangerService populateViewBean(XXService xService) {
		RangerService vService = super.populateViewBean(xService);
		
		HashMap<String, String> configs = new HashMap<String, String>();
		List<XXServiceConfigMap> svcConfigMapList = daoMgr.getXXServiceConfigMap()
				.findByServiceId(xService.getId());
		for(XXServiceConfigMap svcConfMap : svcConfigMapList) {
			String configValue = svcConfMap.getConfigvalue();
			
			if(StringUtils.equalsIgnoreCase(svcConfMap.getConfigkey(), ServiceDBStore.CONFIG_KEY_PASSWORD)) {
				configValue = ServiceDBStore.HIDDEN_PASSWORD_STR;
			}
			configs.put(svcConfMap.getConfigkey(), configValue);
		}
		vService.setConfigs(configs);
		return vService;
	}
	
	public RangerService getPopulatedViewObject(XXService xService) {
		return this.populateViewBean(xService);
	}
	
	public List<RangerService> getAllServices() {
		List<XXService> xxServiceList = daoMgr.getXXService().getAll();
		List<RangerService> serviceList = new ArrayList<RangerService>();
		
		for(XXService xxService : xxServiceList) {
			RangerService service = populateViewBean(xxService);
			serviceList.add(service);
		}
		return serviceList;
	}
	
	public List<XXTrxLog> getTransactionLog(RangerService vService, int action){
		return getTransactionLog(vService, null, action);
	}

	public List<XXTrxLog> getTransactionLog(RangerService vObj, XXService mObj, int action) {
		if (vObj == null || action == 0 || (action == OPERATION_UPDATE_CONTEXT && mObj == null)) {
			return null;
		}
		List<XXTrxLog> trxLogList = new ArrayList<XXTrxLog>();
		Field[] fields = vObj.getClass().getDeclaredFields();

		try {
			Field nameField = vObj.getClass().getDeclaredField("name");
			nameField.setAccessible(true);
			String objectName = "" + nameField.get(vObj);

			for (Field field : fields) {
				if (!trxLogAttrs.containsKey(field.getName())) {
					continue;
				}
				XXTrxLog xTrxLog = processFieldToCreateTrxLog(field,
						objectName, nameField, vObj, mObj, action);
				if (xTrxLog != null) {
					trxLogList.add(xTrxLog);
				}
			}
			Field[] superClassFields = vObj.getClass().getSuperclass().getDeclaredFields();
			for(Field field : superClassFields) {
				if(field.getName().equalsIgnoreCase("isEnabled")) {
					XXTrxLog xTrx = processFieldToCreateTrxLog(field, objectName, nameField, vObj, mObj, action);
					if(xTrx != null) {
						trxLogList.add(xTrx);
					}
					break;
				}
			}
		} catch (IllegalAccessException e) {
			LOG.info("Get transaction log failure." + e);
		} catch (NoSuchFieldException e) {
			LOG.info("Get transaction log failure." + e);
		}
		return trxLogList;
	}

	@SuppressWarnings("unchecked")
	private XXTrxLog processFieldToCreateTrxLog(Field field, String objectName,
			Field nameField, RangerService vObj, XXService mObj, int action) {

		String actionString = "";

		field.setAccessible(true);
		String fieldName = field.getName();
		XXTrxLog xTrxLog = new XXTrxLog();

		try {
			VTrxLogAttr vTrxLogAttr = trxLogAttrs.get(fieldName);

			xTrxLog.setAttributeName(vTrxLogAttr.getAttribUserFriendlyName());

			String value = null;
			boolean isEnum = vTrxLogAttr.isEnum();
			if (isEnum) {

			} else if ("configs".equalsIgnoreCase(fieldName)) {
				Map<String, String> configs = (field.get(vObj) != null) ? (Map<String, String>) field
						.get(vObj) : new HashMap<String, String>();

						value = jsonUtil.readMapToString(configs);
			} else {
				value = "" + field.get(vObj);
			}

			if (action == OPERATION_CREATE_CONTEXT) {
				if (stringUtil.isEmpty(value)) {
					return null;
				}
				xTrxLog.setNewValue(value);
				actionString = actionCreate;
			} else if (action == OPERATION_DELETE_CONTEXT) {
				xTrxLog.setPreviousValue(value);
				actionString = actionDelete;
			} else if (action == OPERATION_UPDATE_CONTEXT) {
				actionString = actionUpdate;
				String oldValue = null;
				Field[] mFields = mObj.getClass().getSuperclass().getDeclaredFields();
				for (Field mField : mFields) {
					mField.setAccessible(true);
					String mFieldName = mField.getName();
					if (fieldName.equalsIgnoreCase(mFieldName)) {
						if (isEnum) {

						} else {
							oldValue = mField.get(mObj) + "";
						}
						break;
					}
				}
				if ("configs".equalsIgnoreCase(fieldName)) {
					Map<String, String> vConfig = jsonUtil.jsonToMap(value);
					RangerService oldService = this.populateViewBean(mObj);
					Map<String, String> xConfig = oldService.getConfigs();

					Map<String, String> newConfig = new HashMap<String, String>();
					Map<String, String> oldConfig = new HashMap<String, String>();

					for (Entry<String, String> entry : vConfig.entrySet()) {

						String key = entry.getKey();
						if (!xConfig.containsKey(key)) {
							if(StringUtils.isNotEmpty(entry.getValue())) {
								newConfig.put(key, entry.getValue());
							}
						} else if (!entry.getValue().equalsIgnoreCase(
								xConfig.get(key))) {
							if (key.equalsIgnoreCase("password")
									&& entry.getValue().equalsIgnoreCase(
											hiddenPasswordString)) {
								continue;
							}
							newConfig.put(key, entry.getValue());
							oldConfig.put(key, xConfig.get(key));
						}
					}
					for (Entry<String, String> entry : xConfig.entrySet()) {
						String key = entry.getKey();
						if (!vConfig.containsKey(key)) {
							oldConfig.put(key, entry.getValue());
							newConfig.put(key,null);
						}
					}
					oldValue = jsonUtil.readMapToString(oldConfig);
					value = jsonUtil.readMapToString(newConfig);
				}
				if ("tagService".equalsIgnoreCase(fieldName)) {
					if(!StringUtils.isEmpty(oldValue) && !"null".equalsIgnoreCase(oldValue)){
						RangerService oldService = this.populateViewBean(mObj);
						oldValue=oldService.getTagService();
					}
				}
				if (oldValue == null || value.equalsIgnoreCase(oldValue)) {
					return null;
				}
				xTrxLog.setPreviousValue(oldValue);
				xTrxLog.setNewValue(value);
			}
		} catch (IllegalArgumentException | IllegalAccessException e) {
			LOG.info("Process field to create trx log failure." + e);
		}

		xTrxLog.setAction(actionString);
		xTrxLog.setObjectClassType(AppConstants.CLASS_TYPE_XA_SERVICE);
		xTrxLog.setObjectId(vObj.getId());
		xTrxLog.setObjectName(objectName);

		XXServiceDef parentObj = daoMgr.getXXServiceDef().findByName(vObj.getType());
		xTrxLog.setParentObjectClassType(AppConstants.CLASS_TYPE_XA_SERVICE_DEF);
		xTrxLog.setParentObjectId(parentObj.getId());
		xTrxLog.setParentObjectName(parentObj.getName());

		return xTrxLog;
	}

	public Map<String, String> getConfigsWithDecryptedPassword(RangerService service) throws IOException {
		Map<String, String> configs = service.getConfigs();
		
		String pwd = configs.get(ServiceDBStore.CONFIG_KEY_PASSWORD);
		if(!stringUtil.isEmpty(pwd) && pwd.equalsIgnoreCase(ServiceDBStore.HIDDEN_PASSWORD_STR)) {
			XXServiceConfigMap pwdConfig = daoMgr.getXXServiceConfigMap().findByServiceAndConfigKey(service.getId(),
					ServiceDBStore.CONFIG_KEY_PASSWORD);
                        if (pwdConfig != null) {
				String encryptedPwd = pwdConfig.getConfigvalue();
                                String decryptedPwd = "";
                                String crypt_algo_array[] = null;
                                if (encryptedPwd.contains(",")) {
                                        crypt_algo_array = encryptedPwd.split(",");
                                }
                                if (crypt_algo_array != null && crypt_algo_array.length > 1) {
                                        String cryptAlgo = null;
                                        String encryptKey = null;
                                        String salt = null;
                                        int iterationCount = 0;
                                        cryptAlgo = crypt_algo_array[0];
                                        encryptKey = crypt_algo_array[1];
                                        salt = crypt_algo_array[2];
                                        iterationCount = Integer.parseInt(crypt_algo_array[3]);

                                        String paddingString = cryptAlgo + "," +  encryptKey + "," + salt + "," + iterationCount;
                                        decryptedPwd = PasswordUtils.decryptPassword(encryptedPwd);

                                        if (StringUtils.equalsIgnoreCase(paddingString + "," + PasswordUtils.encryptPassword(paddingString + "," + decryptedPwd), encryptedPwd)) {
                                                configs.put(ServiceDBStore.CONFIG_KEY_PASSWORD, encryptedPwd);
                                        }
                                } else {
                                        encryptedPwd = pwdConfig.getConfigvalue();
                                        decryptedPwd = PasswordUtils.decryptPassword(encryptedPwd);
                                        if (StringUtils.equalsIgnoreCase(PasswordUtils.encryptPassword(decryptedPwd), encryptedPwd)) {
                                                configs.put(ServiceDBStore.CONFIG_KEY_PASSWORD, encryptedPwd);
                                        }
				}
			}
		}
		return configs;
	}

	public RangerService postCreate(XXService xObj) {
		XXServiceVersionInfo serviceVersionInfo = new XXServiceVersionInfo();

		serviceVersionInfo.setServiceId(xObj.getId());
		serviceVersionInfo.setPolicyVersion(1L);
		serviceVersionInfo.setTagVersion(1L);
		Date now = new Date();
		serviceVersionInfo.setPolicyUpdateTime(now);
		serviceVersionInfo.setTagUpdateTime(now);

		XXServiceVersionInfoDao serviceVersionInfoDao = daoMgr.getXXServiceVersionInfo();

		XXServiceVersionInfo createdServiceVersionInfo = serviceVersionInfoDao.create(serviceVersionInfo);

		return createdServiceVersionInfo != null ? super.postCreate(xObj) : null;
	}

	protected XXService preDelete(Long id) {
		XXService ret = super.preDelete(id);

		if (ret != null) {
			XXServiceVersionInfoDao serviceVersionInfoDao = daoMgr.getXXServiceVersionInfo();

			XXServiceVersionInfo serviceVersionInfo = serviceVersionInfoDao.findByServiceId(id);

			if (serviceVersionInfo != null) {
				serviceVersionInfoDao.remove(serviceVersionInfo.getId());
			}
		}
		return ret;
	}
}
