// 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 com.cloud.dc.dao;

import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.utils.Pair;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import org.springframework.stereotype.Component;

import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
@Local(value={VlanDao.class})
public class VlanDaoImpl extends GenericDaoBase<VlanVO, Long> implements VlanDao {

    private final String FindZoneWideVlans = "SELECT * FROM vlan WHERE data_center_id=? and vlan_type=? and vlan_id!=? and id not in (select vlan_db_id from account_vlan_map)";

    protected SearchBuilder<VlanVO> ZoneVlanIdSearch;
    protected SearchBuilder<VlanVO> ZoneSearch;
    protected SearchBuilder<VlanVO> ZoneTypeSearch;
    protected SearchBuilder<VlanVO> ZoneTypeAllPodsSearch;
    protected SearchBuilder<VlanVO> ZoneTypePodSearch;
    protected SearchBuilder<VlanVO> ZoneVlanSearch;
    protected SearchBuilder<VlanVO> NetworkVlanSearch;
    protected SearchBuilder<VlanVO> PhysicalNetworkVlanSearch;
    protected SearchBuilder<VlanVO> ZoneWideNonDedicatedVlanSearch;
    protected SearchBuilder<VlanVO> VlanGatewaysearch;
    protected SearchBuilder<VlanVO> DedicatedVlanSearch;

    protected SearchBuilder<AccountVlanMapVO> AccountVlanMapSearch;

    @Inject protected PodVlanMapDao _podVlanMapDao;
    @Inject protected AccountVlanMapDao _accountVlanMapDao;
    @Inject protected IPAddressDao _ipAddressDao;

    @Override
    public VlanVO findByZoneAndVlanId(long zoneId, String vlanId) {
        SearchCriteria<VlanVO> sc = ZoneVlanIdSearch.create();
        sc.setParameters("zoneId", zoneId);
        sc.setParameters("vlanId", vlanId);
        return findOneBy(sc);
    }

    @Override
    public List<VlanVO> listByZone(long zoneId) {
        SearchCriteria<VlanVO> sc = ZoneSearch.create();
        sc.setParameters("zoneId", zoneId);
        return listBy(sc);
    }

    public VlanDaoImpl() {
        ZoneVlanIdSearch = createSearchBuilder();
        ZoneVlanIdSearch.and("zoneId", ZoneVlanIdSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        ZoneVlanIdSearch.and("vlanId", ZoneVlanIdSearch.entity().getVlanTag(), SearchCriteria.Op.EQ);
        ZoneVlanIdSearch.done();

        ZoneSearch = createSearchBuilder();
        ZoneSearch.and("zoneId", ZoneSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        ZoneSearch.done();

        ZoneTypeSearch = createSearchBuilder();
        ZoneTypeSearch.and("zoneId", ZoneTypeSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        ZoneTypeSearch.and("vlanType", ZoneTypeSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
        ZoneTypeSearch.done();

        NetworkVlanSearch = createSearchBuilder();
        NetworkVlanSearch.and("networkOfferingId", NetworkVlanSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
        NetworkVlanSearch.done();

        PhysicalNetworkVlanSearch = createSearchBuilder();
        PhysicalNetworkVlanSearch.and("physicalNetworkId", PhysicalNetworkVlanSearch.entity().getPhysicalNetworkId(), SearchCriteria.Op.EQ);
        PhysicalNetworkVlanSearch.done();

        VlanGatewaysearch = createSearchBuilder();
        VlanGatewaysearch.and("gateway", VlanGatewaysearch.entity().getVlanGateway(), SearchCriteria.Op.EQ);
        VlanGatewaysearch.and("networkid", VlanGatewaysearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
        VlanGatewaysearch.done();
    }

    @Override
    public List<VlanVO> listZoneWideVlans(long zoneId, VlanType vlanType, String vlanId){
        SearchCriteria<VlanVO> sc = ZoneVlanSearch.create();
        sc.setParameters("zoneId", zoneId);
        sc.setParameters("vlanId", vlanId);
        sc.setParameters("vlanType", vlanType);
        return listBy(sc);
    }

    @Override
    public List<VlanVO> listByZoneAndType(long zoneId, VlanType vlanType) {
        SearchCriteria<VlanVO> sc = ZoneTypeSearch.create();
        sc.setParameters("zoneId", zoneId);
        sc.setParameters("vlanType", vlanType);
        return listBy(sc);
    }


    @Override
    public List<VlanVO> listByType(VlanType vlanType) {
        SearchCriteria<VlanVO> sc = ZoneTypeSearch.create();
        sc.setParameters("vlanType", vlanType);
        return listBy(sc);
    }

    @Override
    public List<VlanVO> listVlansForPod(long podId) {
        //FIXME: use a join statement to improve the performance (should be minor since we expect only one or two
        List<PodVlanMapVO> vlanMaps = _podVlanMapDao.listPodVlanMapsByPod(podId);
        List<VlanVO> result  = new ArrayList<VlanVO>();
        for (PodVlanMapVO pvmvo: vlanMaps) {
            result.add(findById(pvmvo.getVlanDbId()));
        }
        return result;
    }

    @Override
    public List<VlanVO> listVlansForPodByType(long podId, VlanType vlanType) {
        //FIXME: use a join statement to improve the performance (should be minor since we expect only one or two)
        List<PodVlanMapVO> vlanMaps = _podVlanMapDao.listPodVlanMapsByPod(podId);
        List<VlanVO> result  = new ArrayList<VlanVO>();
        for (PodVlanMapVO pvmvo: vlanMaps) {
            VlanVO vlan =findById(pvmvo.getVlanDbId());
            if (vlan.getVlanType() == vlanType) {
                result.add(vlan);
            }
        }
        return result;
    }

    @Override
    public List<VlanVO> listVlansForAccountByType(Long zoneId, long accountId, VlanType vlanType) {
        //FIXME: use a join statement to improve the performance (should be minor since we expect only one or two)
        List<AccountVlanMapVO> vlanMaps = _accountVlanMapDao.listAccountVlanMapsByAccount(accountId);
        List<VlanVO> result  = new ArrayList<VlanVO>();
        for (AccountVlanMapVO acvmvo: vlanMaps) {
            VlanVO vlan =findById(acvmvo.getVlanDbId());
            if (vlan.getVlanType() == vlanType && (zoneId == null || vlan.getDataCenterId() == zoneId)) {
                result.add(vlan);
            }
        }
        return result;
    }

    @Override
    public void addToPod(long podId, long vlanDbId) {
        PodVlanMapVO pvmvo = new PodVlanMapVO(podId, vlanDbId);
        _podVlanMapDao.persist(pvmvo);

    }

    @Override
    public boolean configure(String name, Map<String, Object> params)
            throws ConfigurationException {
        boolean result = super.configure(name, params);
        ZoneTypeAllPodsSearch = createSearchBuilder();
        ZoneTypeAllPodsSearch.and("zoneId", ZoneTypeAllPodsSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        ZoneTypeAllPodsSearch.and("vlanType", ZoneTypeAllPodsSearch.entity().getVlanType(), SearchCriteria.Op.EQ);

        SearchBuilder<PodVlanMapVO> PodVlanSearch = _podVlanMapDao.createSearchBuilder();
        PodVlanSearch.and("podId", PodVlanSearch.entity().getPodId(), SearchCriteria.Op.NNULL);
        ZoneTypeAllPodsSearch.join("vlan", PodVlanSearch, PodVlanSearch.entity().getVlanDbId(), ZoneTypeAllPodsSearch.entity().getId(), JoinBuilder.JoinType.INNER);

        ZoneTypeAllPodsSearch.done();
        PodVlanSearch.done();

        ZoneTypePodSearch = createSearchBuilder();
        ZoneTypePodSearch.and("zoneId", ZoneTypePodSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        ZoneTypePodSearch.and("vlanType", ZoneTypePodSearch.entity().getVlanType(), SearchCriteria.Op.EQ);

        SearchBuilder<PodVlanMapVO> PodVlanSearch2 = _podVlanMapDao.createSearchBuilder();
        PodVlanSearch2.and("podId", PodVlanSearch2.entity().getPodId(), SearchCriteria.Op.EQ);
        ZoneTypePodSearch.join("vlan", PodVlanSearch2,  PodVlanSearch2.entity().getVlanDbId(), ZoneTypePodSearch.entity().getId(), JoinBuilder.JoinType.INNER);
        PodVlanSearch2.done();
        ZoneTypePodSearch.done();

        ZoneWideNonDedicatedVlanSearch = createSearchBuilder();
        ZoneWideNonDedicatedVlanSearch.and("zoneId", ZoneWideNonDedicatedVlanSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        AccountVlanMapSearch = _accountVlanMapDao.createSearchBuilder();
        AccountVlanMapSearch.and("accountId", AccountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.NULL);
        ZoneWideNonDedicatedVlanSearch.join("AccountVlanMapSearch", AccountVlanMapSearch, ZoneWideNonDedicatedVlanSearch.entity().getId(), AccountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.LEFTOUTER);
        ZoneWideNonDedicatedVlanSearch.done();
        AccountVlanMapSearch.done();

        DedicatedVlanSearch = createSearchBuilder();
        AccountVlanMapSearch = _accountVlanMapDao.createSearchBuilder();
        AccountVlanMapSearch.and("accountId", AccountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
        DedicatedVlanSearch.join("AccountVlanMapSearch", AccountVlanMapSearch, DedicatedVlanSearch.entity().getId(), AccountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.LEFTOUTER);
        DedicatedVlanSearch.done();
        AccountVlanMapSearch.done();

        return result;
    }

    private VlanVO findNextVlan(long zoneId, Vlan.VlanType vlanType) {
        List<VlanVO> allVlans = listByZoneAndType(zoneId, vlanType);
        List<VlanVO> emptyVlans = new ArrayList<VlanVO>();
        List<VlanVO> fullVlans = new ArrayList<VlanVO>();

        // Try to find a VLAN that is partially allocated
        for (VlanVO vlan : allVlans) {
            long vlanDbId = vlan.getId();

            int countOfAllocatedIps = _ipAddressDao.countIPs(zoneId, vlanDbId, true);
            int countOfAllIps = _ipAddressDao.countIPs(zoneId, vlanDbId, false);

            if ((countOfAllocatedIps > 0) && (countOfAllocatedIps < countOfAllIps)) {
                return vlan;
            } else if (countOfAllocatedIps == 0) {
                emptyVlans.add(vlan);
            } else if (countOfAllocatedIps == countOfAllIps) {
                fullVlans.add(vlan);
            }
        }

        if (emptyVlans.isEmpty()) {
            return null;
        }

        // Try to find an empty VLAN with the same tag/subnet as a VLAN that is full
        for (VlanVO fullVlan : fullVlans) {
            for (VlanVO emptyVlan : emptyVlans) {
                if (fullVlan.getVlanTag().equals(emptyVlan.getVlanTag()) && 
                        fullVlan.getVlanGateway().equals(emptyVlan.getVlanGateway()) &&
                        fullVlan.getVlanNetmask().equals(emptyVlan.getVlanNetmask())) {
                    return emptyVlan;
                }
            }
        }

        // Return a random empty VLAN
        return emptyVlans.get(0);
    }

    @Override
    public boolean zoneHasDirectAttachUntaggedVlans(long zoneId) {
        SearchCriteria<VlanVO> sc = ZoneTypeAllPodsSearch.create();
        sc.setParameters("zoneId", zoneId);
        sc.setParameters("vlanType", VlanType.DirectAttached);

        return listIncludingRemovedBy(sc).size() > 0;
    }


    public Pair<String, VlanVO> assignPodDirectAttachIpAddress(long zoneId,
            long podId, long accountId, long domainId) {
        SearchCriteria<VlanVO> sc = ZoneTypePodSearch.create();
        sc.setParameters("zoneId", zoneId);
        sc.setParameters("vlanType", VlanType.DirectAttached);
        sc.setJoinParameters("vlan", "podId", podId);

        VlanVO vlan = findOneIncludingRemovedBy(sc);
        if (vlan == null) {
            return null;
        }

        return null;
//    	String ipAddress = _ipAddressDao.assignIpAddress(accountId, domainId, vlan.getId(), false).getAddress();
//    	if (ipAddress == null) {
//    		return null;
//    	}
//		return new Pair<String, VlanVO>(ipAddress, vlan);

    }

    @Override
    @DB
    public List<VlanVO> searchForZoneWideVlans(long dcId, String vlanType, String vlanId){

        StringBuilder sql = new StringBuilder(FindZoneWideVlans);

        Transaction txn = Transaction.currentTxn();
        PreparedStatement pstmt = null;
        try {
            pstmt = txn.prepareAutoCloseStatement(sql.toString());
            pstmt.setLong(1, dcId);
            pstmt.setString(2, vlanType);
            pstmt.setString(3, vlanId);

            ResultSet rs = pstmt.executeQuery();
            List<VlanVO> zoneWideVlans = new ArrayList<VlanVO>();

            while (rs.next()) {
                zoneWideVlans.add(toEntityBean(rs, false));
            }

            return zoneWideVlans;
        } catch (SQLException e) {
            throw new CloudRuntimeException("Unable to execute " + pstmt.toString(), e);
        }
    }

    @Override
    public List<VlanVO> listVlansByNetworkId(long networkOfferingId) {
        SearchCriteria<VlanVO> sc = NetworkVlanSearch.create();
        sc.setParameters("networkOfferingId", networkOfferingId);
        return listBy(sc);
    }

    @Override
    public List<VlanVO> listVlansByNetworkIdAndGateway(long networkid, String gateway){
        SearchCriteria<VlanVO> sc =  VlanGatewaysearch.create();
        sc.setParameters("networkid", networkid);
        sc.setParameters("gateway", gateway);
        return listBy(sc);
    }

    @Override
    public List<VlanVO> listVlansByPhysicalNetworkId(long physicalNetworkId) {
        SearchCriteria<VlanVO> sc = PhysicalNetworkVlanSearch.create();
        sc.setParameters("physicalNetworkId", physicalNetworkId);
        return listBy(sc);
    }	

    @Override
    public List<VlanVO> listZoneWideNonDedicatedVlans(long zoneId) {
        SearchCriteria<VlanVO> sc = ZoneWideNonDedicatedVlanSearch.create();
        sc.setParameters("ZoneWideNonDedicatedVlanSearch", "zoneId", zoneId);
        return listBy(sc);
    }

    @Override
    public List<VlanVO> listDedicatedVlans(long accountId) {
        SearchCriteria<VlanVO> sc = DedicatedVlanSearch.create();
        sc.setJoinParameters("AccountVlanMapSearch", "accountId", accountId);
        return listBy(sc);
    }

}
