/*
 * 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.biz;

import java.util.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.common.RangerSearchUtil;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.entity.XXSecurityZone;
import org.apache.ranger.entity.XXService;
import org.apache.ranger.entity.XXServiceDef;
import org.apache.ranger.entity.XXTrxLog;
import org.apache.ranger.plugin.model.RangerSecurityZone;
import org.apache.ranger.plugin.model.RangerSecurityZoneHeaderInfo;
import org.apache.ranger.plugin.model.RangerServiceHeaderInfo;
import org.apache.ranger.plugin.model.RangerPrincipal.PrincipalType;
import org.apache.ranger.plugin.model.RangerSecurityZone.RangerSecurityZoneService;
import org.apache.ranger.plugin.model.RangerSecurityZone.SecurityZoneSummary;
import org.apache.ranger.plugin.model.RangerSecurityZone.ZoneServiceSummary;
import org.apache.ranger.plugin.store.AbstractPredicateUtil;
import org.apache.ranger.plugin.store.PList;
import org.apache.ranger.plugin.store.SecurityZonePredicateUtil;
import org.apache.ranger.plugin.store.SecurityZoneStore;
import org.apache.ranger.plugin.util.SearchFilter;
import org.apache.ranger.service.RangerSecurityZoneServiceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class SecurityZoneDBStore implements SecurityZoneStore {
    private static final Logger LOG = LoggerFactory.getLogger(SecurityZoneDBStore.class);
    private static final String RANGER_GLOBAL_STATE_NAME = "RangerSecurityZone";

    @Autowired
    RangerSecurityZoneServiceService securityZoneService;

    @Autowired
    RangerDaoManager daoMgr;

    @Autowired
    RESTErrorUtil restErrorUtil;

    @Autowired
	SecurityZoneRefUpdater securityZoneRefUpdater;

    @Autowired
    RangerBizUtil bizUtil;

    AbstractPredicateUtil predicateUtil = null;

    @Autowired
    ServiceMgr serviceMgr;

    @Autowired
    RangerSearchUtil searchUtil;

    public void init() throws Exception {}

    @PostConstruct
    public void initStore() {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> SecurityZoneDBStore.initStore()");
        }

        predicateUtil = new SecurityZonePredicateUtil();

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== SecurityZoneDBStore.initStore()");
        }
    }

    @Override
    public RangerSecurityZone createSecurityZone(RangerSecurityZone securityZone) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> SecurityZoneDBStore.createSecurityZone()");
        }

        XXSecurityZone xxSecurityZone = daoMgr.getXXSecurityZoneDao().findByZoneName(securityZone.getName());

        if (xxSecurityZone != null) {
            throw restErrorUtil.createRESTException("security-zone with name: " + securityZone.getName() + " already exists", MessageEnums.ERROR_DUPLICATE_OBJECT);
        }

        daoMgr.getXXGlobalState().onGlobalStateChange(RANGER_GLOBAL_STATE_NAME);

        RangerSecurityZone createdSecurityZone = securityZoneService.create(securityZone);
        if (createdSecurityZone == null) {
            throw new Exception("Cannot create security zone:[" + securityZone + "]");
        }
        securityZoneRefUpdater.createNewZoneMappingForRefTable(createdSecurityZone);
        List<XXTrxLog> trxLogList = securityZoneService.getTransactionLog(createdSecurityZone, null, "create");
        bizUtil.createTrxLog(trxLogList);
        return createdSecurityZone;
    }

    @Override
	public RangerSecurityZone updateSecurityZoneById(RangerSecurityZone securityZone) throws Exception {
        RangerSecurityZone oldSecurityZone = securityZoneService.read(securityZone.getId());

        daoMgr.getXXGlobalState().onGlobalStateChange(RANGER_GLOBAL_STATE_NAME);

        RangerSecurityZone updatedSecurityZone = securityZoneService.update(securityZone);
        if (updatedSecurityZone == null) {
            throw new Exception("Cannot update security zone:[" + securityZone + "]");
        }
        securityZoneRefUpdater.createNewZoneMappingForRefTable(updatedSecurityZone);
        boolean isRenamed = !StringUtils.equals(securityZone.getName(), (null == oldSecurityZone) ? null : oldSecurityZone.getName());
		if (isRenamed) {
			securityZoneRefUpdater.updateResourceSignatureWithZoneName(updatedSecurityZone);
		}
        List<XXTrxLog> trxLogList = securityZoneService.getTransactionLog(updatedSecurityZone, oldSecurityZone, "update");
        bizUtil.createTrxLog(trxLogList);
        return securityZone;
    }

    @Override
    public void deleteSecurityZoneByName(String zoneName) throws Exception {
        XXSecurityZone xxSecurityZone = daoMgr.getXXSecurityZoneDao().findByZoneName(zoneName);
        if (xxSecurityZone == null) {
            throw restErrorUtil.createRESTException("security-zone with name: " + zoneName + " does not exist");
        }
        RangerSecurityZone securityZone = securityZoneService.read(xxSecurityZone.getId());

        daoMgr.getXXGlobalState().onGlobalStateChange(RANGER_GLOBAL_STATE_NAME);

        securityZoneRefUpdater.cleanupRefTables(securityZone);

        securityZoneService.delete(securityZone);
        List<XXTrxLog> trxLogList = securityZoneService.getTransactionLog(securityZone, null, "delete");
        bizUtil.createTrxLog(trxLogList);
        }

    @Override
    public void deleteSecurityZoneById(Long zoneId) throws Exception {
        RangerSecurityZone securityZone = securityZoneService.read(zoneId);

        daoMgr.getXXGlobalState().onGlobalStateChange(RANGER_GLOBAL_STATE_NAME);

        securityZoneRefUpdater.cleanupRefTables(securityZone);

        securityZoneService.delete(securityZone);
        List<XXTrxLog> trxLogList = securityZoneService.getTransactionLog(securityZone, null, "delete");
        bizUtil.createTrxLog(trxLogList);
    }

    @Override
    public RangerSecurityZone getSecurityZone(Long id) throws Exception {
        return securityZoneService.read(id);
    }

    @Override
    public RangerSecurityZone getSecurityZoneByName(String name) throws Exception {
        XXSecurityZone xxSecurityZone = daoMgr.getXXSecurityZoneDao().findByZoneName(name);
        if (xxSecurityZone == null) {
            throw restErrorUtil.createRESTException("security-zone with name: " + name + " does not exist");
        }
        return securityZoneService.read(xxSecurityZone.getId());
    }

    @Override
    public List<RangerSecurityZone> getSecurityZones(SearchFilter filter) throws Exception {
        List<RangerSecurityZone> ret = new ArrayList<>();

        List<XXSecurityZone> xxSecurityZones = daoMgr.getXXSecurityZoneDao().getAll();

        for (XXSecurityZone xxSecurityZone : xxSecurityZones) {
            if (!xxSecurityZone.getId().equals(RangerSecurityZone.RANGER_UNZONED_SECURITY_ZONE_ID)) {
                ret.add(securityZoneService.read(xxSecurityZone.getId()));
            }
        }

        if (CollectionUtils.isNotEmpty(ret) && filter != null) {
            List<RangerSecurityZone> copy = new ArrayList<>(ret);

            predicateUtil.applyFilter(copy, filter);
            ret = copy;
        }

        return ret;
    }

    @Override
    public Map<String, RangerSecurityZone.RangerSecurityZoneService> getSecurityZonesForService(String serviceName) {
        Map<String, RangerSecurityZone.RangerSecurityZoneService> ret = null;

        SearchFilter filter = new SearchFilter();
        filter.setParam(SearchFilter.SERVICE_NAME, serviceName);

        try {
            List<RangerSecurityZone> matchingZones = getSecurityZones(filter);

            if (CollectionUtils.isNotEmpty(matchingZones)) {
                ret = new HashMap<>();

                for (RangerSecurityZone matchingZone : matchingZones) {
                    ret.put(matchingZone.getName(), matchingZone.getServices().get(serviceName));
                }
            }
        } catch (Exception excp) {
            LOG.error("Failed to get security zones for service:[" + serviceName + "]", excp);
        }

        return ret;
    }

    public List<RangerSecurityZoneHeaderInfo> getSecurityZoneHeaderInfoList(HttpServletRequest request) {
        String  namePrefix         = request.getParameter(SearchFilter.ZONE_NAME_PREFIX);
        boolean filterByNamePrefix = StringUtils.isNotBlank(namePrefix);

        List<RangerSecurityZoneHeaderInfo> ret = daoMgr.getXXSecurityZoneDao().findAllZoneHeaderInfos();

        if (!ret.isEmpty() && filterByNamePrefix) {
            for (ListIterator<RangerSecurityZoneHeaderInfo> iter = ret.listIterator(); iter.hasNext(); ) {
                RangerSecurityZoneHeaderInfo zoneHeader = iter.next();

                if (!StringUtils.startsWithIgnoreCase(zoneHeader.getName(), namePrefix)) {
                    iter.remove();
                }
            }
        }

        return ret;
    }

    public List<RangerServiceHeaderInfo> getServiceHeaderInfoListByZoneId(Long zoneId, HttpServletRequest request) {
        String  namePrefix         = request.getParameter(SearchFilter.SERVICE_NAME_PREFIX);
        boolean filterByNamePrefix = StringUtils.isNotBlank(namePrefix);

        List<RangerServiceHeaderInfo> services    = daoMgr.getXXSecurityZoneRefService().findServiceHeaderInfosByZoneId(zoneId);
        List<RangerServiceHeaderInfo> tagServices = daoMgr.getXXSecurityZoneRefTagService().findServiceHeaderInfosByZoneId(zoneId);
        List<RangerServiceHeaderInfo> ret         = new ArrayList<>(services.size() + tagServices.size());

        ret.addAll(services);
        ret.addAll(tagServices);

        if (!ret.isEmpty() && filterByNamePrefix) {
            for (ListIterator<RangerServiceHeaderInfo> iter = ret.listIterator(); iter.hasNext(); ) {
                RangerServiceHeaderInfo serviceHeader = iter.next();

                if (!StringUtils.startsWithIgnoreCase(serviceHeader.getName(), namePrefix)) {
                    iter.remove();
                }
            }
        }

        return ret;
    }

    public List<RangerSecurityZoneHeaderInfo> getSecurityZoneHeaderInfoListByServiceId(Long serviceId, Boolean isTagService, HttpServletRequest request) {
        if (serviceId == null){
            throw restErrorUtil.createRESTException("Invalid value for serviceId", MessageEnums.INVALID_INPUT_DATA);
        }

        String  namePrefix         = request.getParameter(SearchFilter.ZONE_NAME_PREFIX);
        boolean filterByNamePrefix = StringUtils.isNotBlank(namePrefix);

        List<RangerSecurityZoneHeaderInfo> ret = daoMgr.getXXSecurityZoneDao().findAllZoneHeaderInfosByServiceId(serviceId, isTagService);

        if (!ret.isEmpty() && filterByNamePrefix) {
            for (ListIterator<RangerSecurityZoneHeaderInfo> iter = ret.listIterator(); iter.hasNext(); ) {
                RangerSecurityZoneHeaderInfo zoneHeader = iter.next();

                if (!StringUtils.startsWithIgnoreCase(zoneHeader.getName(), namePrefix)) {
                    iter.remove();
                }
            }
        }

        return ret;
    }

    public PList<SecurityZoneSummary> getZonesSummary(SearchFilter filter) throws Exception {
        int maxRows    = filter.getMaxRows();
        int startIndex = filter.getStartIndex();

        filter.setStartIndex(0);
        filter.setMaxRows(0);

        List<RangerSecurityZone>  securityZones = getSecurityZones(filter);
        List<SecurityZoneSummary> summaryList   = new ArrayList<>();

        for (RangerSecurityZone securityZone : securityZones) {
            if (bizUtil.isAdmin() || serviceMgr.isZoneAdmin(securityZone.getName()) || serviceMgr.isZoneAuditor(securityZone.getName())) {
                summaryList.add(toSecurityZoneSummary(securityZone));
            }
        }

        List<SecurityZoneSummary>  paginatedList;

        if (summaryList.size() > startIndex) {
            int endIndex = Math.min((startIndex + maxRows), summaryList.size());

            paginatedList = summaryList.subList(startIndex, endIndex);
        } else {
            paginatedList = Collections.emptyList();
        }

        PList<SecurityZoneSummary> ret = new PList<>(paginatedList, startIndex, maxRows, summaryList.size(), paginatedList.size(), filter.getSortType(), filter.getSortBy());

        return ret;
    }

    private SecurityZoneSummary toSecurityZoneSummary(RangerSecurityZone securityZone) {
        SecurityZoneSummary ret = new SecurityZoneSummary();

        ret.setId(securityZone.getId());
        ret.setName(securityZone.getName());
        ret.setDescription(securityZone.getDescription());
        ret.setGuid(securityZone.getGuid());
        ret.setCreateTime(securityZone.getCreateTime());
        ret.setUpdateTime(securityZone.getUpdateTime());
        ret.setCreatedBy(securityZone.getCreatedBy());
        ret.setUpdatedBy(securityZone.getUpdatedBy());
        ret.setVersion(ret.getVersion());
        ret.setIsEnabled(securityZone.getIsEnabled());
        ret.setTagServices(securityZone.getTagServices());

        Map<PrincipalType, Integer> adminCount   = new HashMap<>();
        Map<PrincipalType, Integer> auditorCount = new HashMap<>();

        adminCount.put(PrincipalType.USER, securityZone.getAdminUsers().size());
        adminCount.put(PrincipalType.GROUP, securityZone.getAdminUserGroups().size());
        adminCount.put(PrincipalType.ROLE, securityZone.getAdminRoles().size());

        auditorCount.put(PrincipalType.USER, securityZone.getAuditUsers().size());
        auditorCount.put(PrincipalType.GROUP, securityZone.getAuditUserGroups().size());
        auditorCount.put(PrincipalType.ROLE, securityZone.getAuditRoles().size());

        ret.setAdminCount(adminCount);
        ret.setAuditorCount(auditorCount);

        List<ZoneServiceSummary> services = getSecurityZoneServiceSummary(securityZone);

        ret.setServices(services);
        ret.setTotalResourceCount(services.stream().mapToLong(ZoneServiceSummary::getResourceCount).sum());

        return ret;
    }

    private List<ZoneServiceSummary> getSecurityZoneServiceSummary(RangerSecurityZone securityZone) {
        List<ZoneServiceSummary> ret = new ArrayList<>();

        if(MapUtils.isNotEmpty(securityZone.getServices())) {
            for(Map.Entry<String, RangerSecurityZoneService> entry : securityZone.getServices().entrySet()) {
                String                    serviceName = entry.getKey();
                RangerSecurityZoneService zoneService = entry.getValue();
                XXService                 xService    = daoMgr.getXXService().findByName(serviceName);
                XXServiceDef              serviceDef  = daoMgr.getXXServiceDef().getById(xService.getType());
                ZoneServiceSummary        summary     = new ZoneServiceSummary();

                summary.setId(xService.getId());
                summary.setName(serviceName);
                summary.setType(serviceDef.getName());
                summary.setDisplayName(xService.getDisplayName());
                summary.setResourceCount((long)zoneService.getResources().size());

                ret.add(summary);
            }
        }

        return ret;
    }
}
