package ee.ut.math.tvt2008.salessystem.domain.controller.impl;

import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.Transaction;

import ee.ut.math.tvt2008.salessystem.domain.controller.SalesDomainController;
import ee.ut.math.tvt2008.salessystem.domain.data.Client;
import ee.ut.math.tvt2008.salessystem.domain.data.Sale;
import ee.ut.math.tvt2008.salessystem.domain.data.SoldItem;
import ee.ut.math.tvt2008.salessystem.domain.data.StockItem;
import ee.ut.math.tvt2008.salessystem.util.HibernateUtil;

/**
 * Implementation of the sales domain controller.
 */
public class SalesDomainControllerImpl implements SalesDomainController {

    private static final Logger log = Logger.getLogger(SalesDomainControllerImpl.class);
    private Session session = HibernateUtil.currentSession();

    public void submitCurrentPurchase(List<StockItem> goods, Client currentClient) {
        // Let's assume we have checked and found out that the buyer is
        // underaged and
        // cannot buy chupa-chups
        // throw new VerificationFailedException("Underaged!");
        // begin transaction
        Transaction tx = session.beginTransaction();

        // construct new sale object
        Sale sale = new Sale();
        sale.setId(null);
        sale.setSellingTime(new Date());
        // set client who made the sale
        sale.setClient(currentClient);

        for (StockItem item : goods) {
            // copy warehouse data to sold item
            SoldItem soldItem = new SoldItem();

            soldItem.setName(item.getName());
            soldItem.setPrice(item.getPrice());
            soldItem.setQuantity(item.getQuantity());
            soldItem.setSale(sale);
            // set connection to warehouse item
            soldItem.setStockItem(item);

            // add sold item to sale
            sale.addSoldItem(soldItem);

            // reduce stock quantity
            StockItem stockItem = getStockItemById(item.getId());
            stockItem.setQuantity(stockItem.getQuantity() - soldItem.getQuantity());
            session.save(stockItem);
        }
        session.save(sale);

        // end transaction
        tx.commit();
    }

    public void cancelCurrentPurchase() {
        // XXX - Cancel current purchase
        log.info("Current purchase canceled");
    }

    public void startNewPurchase() {
        // XXX - Start new purchase
        log.info("New purchase started");
    }

    @SuppressWarnings("unchecked")
    public List<StockItem> loadWarehouseState() {
        List<StockItem> result = session.createQuery("from StockItem").list();
        log.info(result.size() + " items loaded from disk");

        return result;
    }

    @SuppressWarnings("unchecked")
    public Sale findSaleInfo(Long id) {
        List<Sale> result = session.createQuery("from Sale where id=?").setLong(0, id).list();

        if (result.size() > 0) {
            Sale sale = result.get(0);
            log.info(sale.getSoldItems().size() + " items found");
            return sale;
        }

        return null;
    }

    @SuppressWarnings("unchecked")
    public List<Sale> loadPurchaseHistory() {
        List<Sale> result = session.createQuery("from Sale").list();
        log.info(result.size() + " purchases loaded from disk");

        return result;
    }

    @SuppressWarnings("unchecked")
    public List<Client> loadAllClients() {
        List<Client> clients = session.createQuery("from Client").list();
        log.info(clients.size() + " clients loaded from disk");
        
        return clients;
    }
    
    @SuppressWarnings("unchecked")
    public Client getClientById(long id) {
        List<Client> clients = session.createQuery("from Client where id=?").setLong(0, id).list();
        if (clients.size() > 0) {
            return clients.get(0);
        }

        return null;
    }

    @SuppressWarnings("unchecked")
    private StockItem getStockItemById(long id) {
        List<StockItem> items = session.createQuery("from StockItem where id=?").setLong(0, id).list();
        if (items.size() > 0) {
            return items.get(0);
        }

        return null;
    }

    public void addStockItem(final StockItem stockItem) {
        Transaction tx = session.beginTransaction();
        if(stockItem!=null)
        session.save(stockItem);
        tx.commit();
    }
    public void addClient(final Client client){
        Transaction tx = session.beginTransaction();
            session.save(client);
           
            log.debug("Added " + client.getName() + " to the client list");
        tx.commit();
    }
    
    public Session getSession(){
        return session;
    }
}
