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

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.ejb.Local;

import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.UpdateBuilder;

@Component
@Local(value={VMTemplatePoolDao.class})
public class VMTemplatePoolDaoImpl extends GenericDaoBase<VMTemplateStoragePoolVO, Long> implements VMTemplatePoolDao {
	public static final Logger s_logger = Logger.getLogger(VMTemplatePoolDaoImpl.class.getName());
	
	protected final SearchBuilder<VMTemplateStoragePoolVO> PoolSearch;
	protected final SearchBuilder<VMTemplateStoragePoolVO> TemplateSearch;
	protected final SearchBuilder<VMTemplateStoragePoolVO> PoolTemplateSearch;
	protected final SearchBuilder<VMTemplateStoragePoolVO> TemplateStatusSearch;
    protected final SearchBuilder<VMTemplateStoragePoolVO> TemplatePoolStatusSearch;
	protected final SearchBuilder<VMTemplateStoragePoolVO> TemplateStatesSearch;
	protected final SearchBuilder<VMTemplateStoragePoolVO> updateStateSearch;
	
	protected static final String UPDATE_TEMPLATE_HOST_REF =
		"UPDATE template_spool_ref SET download_state = ?, download_pct= ?, last_updated = ? "
	+   ", error_str = ?, local_path = ?, job_id = ? "
	+   "WHERE pool_id = ? and template_id = ?";
	
	protected static final String DOWNLOADS_STATE_DC=
		"SELECT * FROM template_spool_ref t, storage_pool p where t.pool_id = p.id and p.data_center_id=? "
	+	" and t.template_id=? and t.download_state = ?" ;
	
	protected static final String DOWNLOADS_STATE_DC_POD=
		"SELECT * FROM template_spool_ref tp, storage_pool_host_ref ph, host h where tp.pool_id = ph.pool_id and ph.host_id = h.id and h.data_center_id=? and h.pod_id=? "
	+	" and tp.template_id=? and tp.download_state=?" ;
	
	protected static final String HOST_TEMPLATE_SEARCH=
		"SELECT * FROM template_spool_ref tp, storage_pool_host_ref ph, host h where tp.pool_id = ph.pool_id and ph.host_id = h.id and h.id=? "
	+	" and tp.template_id=? " ;
	
	
	public VMTemplatePoolDaoImpl () {
		PoolSearch = createSearchBuilder();
		PoolSearch.and("pool_id", PoolSearch.entity().getPoolId(), SearchCriteria.Op.EQ);
		PoolSearch.done();
		
		TemplateSearch = createSearchBuilder();
		TemplateSearch.and("template_id", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
		TemplateSearch.done();
		
		PoolTemplateSearch = createSearchBuilder();
		PoolTemplateSearch.and("pool_id", PoolTemplateSearch.entity().getPoolId(), SearchCriteria.Op.EQ);
		PoolTemplateSearch.and("template_id", PoolTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
		PoolTemplateSearch.done();
		
		TemplateStatusSearch = createSearchBuilder();
		TemplateStatusSearch.and("template_id", TemplateStatusSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
		TemplateStatusSearch.and("download_state", TemplateStatusSearch.entity().getDownloadState(), SearchCriteria.Op.EQ);
		TemplateStatusSearch.done();

		TemplatePoolStatusSearch = createSearchBuilder();
		TemplatePoolStatusSearch.and("pool_id", TemplatePoolStatusSearch.entity().getPoolId(), SearchCriteria.Op.EQ);
		TemplatePoolStatusSearch.and("template_id", TemplatePoolStatusSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
		TemplatePoolStatusSearch.and("download_state", TemplatePoolStatusSearch.entity().getDownloadState(), SearchCriteria.Op.EQ);
		TemplatePoolStatusSearch.done();

        TemplateStatesSearch = createSearchBuilder();
		TemplateStatesSearch.and("template_id", TemplateStatesSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
		TemplateStatesSearch.and("states", TemplateStatesSearch.entity().getDownloadState(), SearchCriteria.Op.IN);
		TemplateStatesSearch.done();

		updateStateSearch = this.createSearchBuilder();
		updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ);
		updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ);
		updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ);
		updateStateSearch.done();
	}

	@Override
	public List<VMTemplateStoragePoolVO> listByPoolId(long id) {
	    SearchCriteria<VMTemplateStoragePoolVO> sc = PoolSearch.create();
	    sc.setParameters("pool_id", id);
	    return listIncludingRemovedBy(sc);
	}

	@Override
	public List<VMTemplateStoragePoolVO> listByTemplateId(long templateId) {
	    SearchCriteria<VMTemplateStoragePoolVO> sc = TemplateSearch.create();
	    sc.setParameters("template_id", templateId);
	    return listIncludingRemovedBy(sc);
	}

	@Override
	public VMTemplateStoragePoolVO findByPoolTemplate(long hostId, long templateId) {
		SearchCriteria<VMTemplateStoragePoolVO> sc = PoolTemplateSearch.create();
	    sc.setParameters("pool_id", hostId);
	    sc.setParameters("template_id", templateId);
	    return findOneIncludingRemovedBy(sc);
	}

	@Override
	public List<VMTemplateStoragePoolVO> listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState) {
		SearchCriteria<VMTemplateStoragePoolVO> sc = TemplateStatusSearch.create();
		sc.setParameters("template_id", templateId);
		sc.setParameters("download_state", downloadState.toString());
		return listIncludingRemovedBy(sc);
	}

	@Override
    public List<VMTemplateStoragePoolVO> listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState, long poolId) {
        SearchCriteria<VMTemplateStoragePoolVO> sc = TemplatePoolStatusSearch.create();
        sc.setParameters("pool_id", poolId);
        sc.setParameters("template_id", templateId);
        sc.setParameters("download_state", downloadState.toString());
        return listIncludingRemovedBy(sc);
    }

	@Override
	public List<VMTemplateStoragePoolVO> listByTemplateStatus(long templateId, long datacenterId, VMTemplateStoragePoolVO.Status downloadState) {
        Transaction txn = Transaction.currentTxn();
		PreparedStatement pstmt = null;
		List<VMTemplateStoragePoolVO> result = new ArrayList<VMTemplateStoragePoolVO>();
		try {
			String sql = DOWNLOADS_STATE_DC;
			pstmt = txn.prepareAutoCloseStatement(sql);
			pstmt.setLong(1, datacenterId);
			pstmt.setLong(2, templateId);
			pstmt.setString(3, downloadState.toString());
			ResultSet rs = pstmt.executeQuery();
			while (rs.next()) {
                result.add(toEntityBean(rs, false));
            }
		} catch (Exception e) {
			s_logger.warn("Exception: ", e);
		}
		return result;

	}
	
	@Override
	public List<VMTemplateStoragePoolVO> listByTemplateStatus(long templateId, long datacenterId, long podId, VMTemplateStoragePoolVO.Status downloadState) {
        Transaction txn = Transaction.currentTxn();
		PreparedStatement pstmt = null;
		List<VMTemplateStoragePoolVO> result = new ArrayList<VMTemplateStoragePoolVO>();
		ResultSet rs = null;
		try {
			String sql = DOWNLOADS_STATE_DC_POD;
			pstmt = txn.prepareStatement(sql);
			
			pstmt.setLong(1, datacenterId);
			pstmt.setLong(2, podId);
			pstmt.setLong(3, templateId);
			pstmt.setString(4, downloadState.toString());
			rs = pstmt.executeQuery();
			while (rs.next()) {
                // result.add(toEntityBean(rs, false)); TODO: this is buggy in GenericDaoBase for hand constructed queries
				long id = rs.getLong(1); //ID column
				result.add(findById(id));
            }
		} catch (Exception e) {
			s_logger.warn("Exception: ", e);
		} finally {
			try {
				if (rs != null) {
					rs.close();
				}
				if (pstmt != null) {
					pstmt.close();
				}
			} catch (SQLException e) {
			}
		}
		return result;

	}
	
	public List<VMTemplateStoragePoolVO> listByHostTemplate(long hostId, long templateId) {
        Transaction txn = Transaction.currentTxn();
		PreparedStatement pstmt = null;
		List<VMTemplateStoragePoolVO> result = new ArrayList<VMTemplateStoragePoolVO>();
		ResultSet rs = null;
		try {
			String sql = HOST_TEMPLATE_SEARCH;
			pstmt = txn.prepareStatement(sql);
			
			pstmt.setLong(1, hostId);
			pstmt.setLong(2, templateId);
			rs = pstmt.executeQuery();
			while (rs.next()) {
                // result.add(toEntityBean(rs, false)); TODO: this is buggy in GenericDaoBase for hand constructed queries
				long id = rs.getLong(1); //ID column
				result.add(findById(id));
            }
		} catch (Exception e) {
			s_logger.warn("Exception: ", e);
		} finally {
			try {
				if (rs != null) {
					rs.close();
				}
				if (pstmt != null) {
					pstmt.close();
				}
			} catch (SQLException e) {
			}
		}
		return result;

	}

	@Override
	public boolean templateAvailable(long templateId, long hostId) {
		VMTemplateStorageResourceAssoc tmpltPool = findByPoolTemplate(hostId, templateId);
		if (tmpltPool == null)
		  return false;
		
		return tmpltPool.getDownloadState()==Status.DOWNLOADED;
	}

	@Override
	public List<VMTemplateStoragePoolVO> listByTemplateStates(long templateId, VMTemplateStoragePoolVO.Status... states) {
    	SearchCriteria<VMTemplateStoragePoolVO> sc = TemplateStatesSearch.create();
    	sc.setParameters("states", (Object[])states);
		sc.setParameters("template_id", templateId);

	  	return search(sc, null);
	}

	@Override
	public VMTemplateStoragePoolVO findByHostTemplate(Long hostId, Long templateId) {
		List<VMTemplateStoragePoolVO> result = listByHostTemplate(hostId, templateId);
		return (result.size() == 0)?null:result.get(1);
	}

    @Override
    public boolean updateState(State currentState, Event event,
            State nextState, DataObjectInStore vo, Object data) {
        VMTemplateStoragePoolVO templatePool = (VMTemplateStoragePoolVO)vo;
        Long oldUpdated = templatePool.getUpdatedCount();
        Date oldUpdatedTime = templatePool.getUpdated();
    
        SearchCriteria<VMTemplateStoragePoolVO> sc = updateStateSearch.create();
        sc.setParameters("id", templatePool.getId());
        sc.setParameters("state", currentState);
        sc.setParameters("updatedCount", templatePool.getUpdatedCount());

        templatePool.incrUpdatedCount();

        UpdateBuilder builder = getUpdateBuilder(vo);
        builder.set(vo, "state", nextState);
        builder.set(vo, "updated", new Date());

        int rows = update((VMTemplateStoragePoolVO) vo, sc);
        if (rows == 0 && s_logger.isDebugEnabled()) {
            VMTemplateStoragePoolVO dbVol = findByIdIncludingRemoved(templatePool.getId());
            if (dbVol != null) {
                StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString());
                str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()).append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=")
                        .append(dbVol.getUpdated());
                str.append(": New Data={id=").append(templatePool.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(templatePool.getUpdatedCount())
                        .append("; updatedTime=").append(templatePool.getUpdated());
                str.append(": stale Data={id=").append(templatePool.getId()).append("; state=").append(currentState).append("; event=").append(event).append("; updatecount=").append(oldUpdated)
                        .append("; updatedTime=").append(oldUpdatedTime);
            } else {
                s_logger.debug("Unable to update objectIndatastore: id=" + templatePool.getId() + ", as there is no such object exists in the database anymore");
            }
        }
        return rows > 0;
    }

}
