package com.jh.radegast.rating;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.hibernate.query.NativeQuery;
import org.springframework.stereotype.Repository;

import com.jh.common.jpa.AbstractHibernateRepository;
import com.jh.common.web.list.Page;
import com.jh.common.web.list.PagingInfo;
import com.jh.radegast.api.RatingsFilter;
import com.jh.radegast.model.Rating;
import com.jh.radegast.model.RatingStat;


@Repository
public class RatingRepository extends AbstractHibernateRepository {

	public void saveBulk(Collection<Rating> ratings) {
		if (ratings == null || ratings.isEmpty()) {
			return;
		}
		
		for (Rating r : ratings) {
			r.setCreated(new Date(Long.parseLong(r.getKey())));
			save(r);
		}
	}


	public List<Rating> fetchByKeys(Set<String> keySet) {
		if (keySet == null || keySet.isEmpty()) {
			return Collections.emptyList();
		}
		
		return criteria(Rating.class).add(Restrictions.in("key", keySet)).list();
	}


	public Page<Rating> filter(RatingsFilter ratingsFilter, PagingInfo pagingInfo) {
		return pagedResult(filterCriteria(ratingsFilter), pagingInfo);
	}


	public List<Rating> filter(RatingsFilter ratingsFilter) {
		return filterCriteria(ratingsFilter).list();
	}
	
	
    protected Criteria filterCriteria(RatingsFilter filter) {
    	Criteria c = criteria(Rating.class);
    	
    	if (filter != null) {
			if (filter.getFrom() != null) {
                c.add(Restrictions.ge("key", String.valueOf(filter.getFrom().getTime())));
            }
            if (filter.getTo() != null) {
                c.add(Restrictions.le("key", String.valueOf(filter.getTo().getTime())));
            }
        }

    	return c;
    }

    
    public List<RatingStat> stats(RatingsFilter filter) {
    	StringBuilder sql = new StringBuilder("select rating, count(*) from rating where 1=1");
    	if (filter != null) {
			if (filter.getFrom() != null) {
                sql.append(" and key >= :from ");
            }
            if (filter.getTo() != null) {
                sql.append(" and key <= :to ");
            }
    	}
    	sql.append(" group by rating");
    	
    	NativeQuery query = getSession().createNativeQuery(sql.toString());

    	if (filter != null) {
			if (filter.getFrom() != null) {
				query.setParameter("from", String.valueOf(filter.getFrom().getTime()));
            }
            if (filter.getTo() != null) {
				query.setParameter("to", String.valueOf(filter.getTo().getTime()));
            }
    	}

    	List<RatingStat> stats = new ArrayList<>();
    	List<Object[]> rows = query.list();
    	if (rows != null) {
    		for (Object[] row : rows) {
    			stats.add(new RatingStat(((Number) row[0]).longValue(), ((Number) row[1]).longValue()));
    		}
    	}
    	
    	return stats;
    }

}
