// 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.event.dao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import javax.ejb.Local;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.cloud.dc.Vlan;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventVO;
import com.cloud.utils.DateUtil;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;

@Component
@Local(value={UsageEventDao.class})
public class UsageEventDaoImpl extends GenericDaoBase<UsageEventVO, Long> implements UsageEventDao {
    public static final Logger s_logger = Logger.getLogger(UsageEventDaoImpl.class.getName());

    private final SearchBuilder<UsageEventVO> latestEventsSearch;
    private final SearchBuilder<UsageEventVO> IpeventsSearch;
    private static final String COPY_EVENTS = "INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size) " +
            "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size FROM cloud.usage_event vmevt WHERE vmevt.id > ? and vmevt.id <= ? ";
    private static final String COPY_ALL_EVENTS = "INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size) " +
            "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size FROM cloud.usage_event vmevt WHERE vmevt.id <= ?";
    private static final String MAX_EVENT = "select max(id) from cloud.usage_event where created <= ?";


    public UsageEventDaoImpl () {
        latestEventsSearch = createSearchBuilder();
        latestEventsSearch.and("processed", latestEventsSearch.entity().isProcessed(), SearchCriteria.Op.EQ);
        latestEventsSearch.and("enddate", latestEventsSearch.entity().getCreateDate(), SearchCriteria.Op.LTEQ);
        latestEventsSearch.done();

        IpeventsSearch = createSearchBuilder();
        IpeventsSearch.and("startdate", IpeventsSearch.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
        IpeventsSearch.and("enddate", IpeventsSearch.entity().getCreateDate(), SearchCriteria.Op.LTEQ);
        IpeventsSearch.and("zoneid", IpeventsSearch.entity().getZoneId(), SearchCriteria.Op.EQ);
        IpeventsSearch.and("networktype", IpeventsSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
        IpeventsSearch.and().op("assignEvent", IpeventsSearch.entity().getType(), SearchCriteria.Op.EQ);
        IpeventsSearch.or("releaseEvent", IpeventsSearch.entity().getType(), SearchCriteria.Op.EQ);
        IpeventsSearch.closeParen();
        IpeventsSearch.done();
    }

    @Override
    public List<UsageEventVO> listLatestEvents(Date endDate) {
        Filter filter = new Filter(UsageEventVO.class, "createDate", Boolean.TRUE, null, null);
        SearchCriteria<UsageEventVO> sc = latestEventsSearch.create();
        sc.setParameters("processed", false);
        sc.setParameters("enddate", endDate);
        return listBy(sc, filter);
    }

    @Override
    public List<UsageEventVO> getLatestEvent() {
        Filter filter = new Filter(UsageEventVO.class, "id", Boolean.FALSE, Long.valueOf(0), Long.valueOf(1));
        return listAll(filter);
    }

    @Override
    @DB
    public synchronized List<UsageEventVO> getRecentEvents(Date endDate) {
        long recentEventId = getMostRecentEventId();
        long maxEventId = getMaxEventId(endDate);
        Transaction txn = Transaction.open(Transaction.USAGE_DB);
        String sql = COPY_EVENTS;
        if (recentEventId == 0) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("no recent event date, copying all events");
            }
            sql = COPY_ALL_EVENTS;
        }

        PreparedStatement pstmt = null;
        try {
            txn.start();
            pstmt = txn.prepareAutoCloseStatement(sql);
            int i = 1;
            if (recentEventId != 0) {
                pstmt.setLong(i++, recentEventId);
            }
            pstmt.setLong(i++, maxEventId);
            pstmt.executeUpdate();
            txn.commit();
            return findRecentEvents(endDate);
        } catch (Exception ex) {
            txn.rollback();
            s_logger.error("error copying events from cloud db to usage db", ex);
            throw new CloudRuntimeException(ex.getMessage());
        }
    }

    @DB
    private long getMostRecentEventId() {
        Transaction txn = Transaction.open(Transaction.USAGE_DB);
        try {
            List<UsageEventVO> latestEvents = getLatestEvent();

            if(latestEvents !=null && latestEvents.size() == 1){
                UsageEventVO latestEvent = latestEvents.get(0);
                if(latestEvent != null){
                    return latestEvent.getId();
                }
            }
            return 0;
        } catch (Exception ex) {
            s_logger.error("error getting most recent event id", ex);
            throw new CloudRuntimeException(ex.getMessage());
        } finally {
            txn.close();
        }
    }

    private List<UsageEventVO> findRecentEvents(Date endDate) {
        Transaction txn = Transaction.open(Transaction.USAGE_DB);
        try {
            return listLatestEvents(endDate);
        } catch (Exception ex) {
            s_logger.error("error getting most recent event date", ex);
            throw new CloudRuntimeException(ex.getMessage());
        } finally {
            txn.close();
        }
    }

    private long getMaxEventId(Date endDate) {
        Transaction txn = Transaction.currentTxn();
        PreparedStatement pstmt = null;
        try {
            String sql = MAX_EVENT;
            pstmt = txn.prepareAutoCloseStatement(sql);
            pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), endDate));
            ResultSet rs = pstmt.executeQuery();
            if (rs.next()) {
                return Long.valueOf(rs.getLong(1));
            }
            return 0;
        } catch (Exception ex) {
            s_logger.error("error getting max event id", ex);
            throw new CloudRuntimeException(ex.getMessage());
        } finally {
            txn.close();
        }
    }

    @Override
    public List<UsageEventVO> listDirectIpEvents(Date startDate, Date endDate, long zoneId) {
        Filter filter = new Filter(UsageEventVO.class, "createDate", Boolean.TRUE, null, null);
        SearchCriteria<UsageEventVO> sc = IpeventsSearch.create();
        sc.setParameters("startdate", startDate);
        sc.setParameters("enddate", endDate);
        sc.setParameters("assignEvent", EventTypes.EVENT_NET_IP_ASSIGN);
        sc.setParameters("releaseEvent", EventTypes.EVENT_NET_IP_RELEASE);
        sc.setParameters("zoneid", zoneId);
        sc.setParameters("networktype", Vlan.VlanType.DirectAttached.toString());
        return listBy(sc, filter);
    }

}
