package com.jens.rhasspy.shoppinglist;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;

import org.apache.commons.lang3.StringUtils;

public class Unit
{
static ArrayList<Unit> unitCache = null;
	
	long id;
	String name;
	String abbreviation;
	boolean isDefault;
	boolean isDummy;
	boolean isPiece;
	
	public long getId()
	{
		return id;
	}
	public void setId(long id)
	{
		this.id = id;
	}
	
	public String getMainName()
	{
		if(name.contains(";"))
			return name.split(";")[0];
		else
			return name;
	}
	
	public String getName()
	{
		return name;
	}
	public void setName(String name)
	{
		this.name = name;
	}
	
	public String getAbbreviation()
	{
		return abbreviation;
	}
	public void setAbbreviation(String abbreviation)
	{
		this.abbreviation = abbreviation;
	}
	
	public boolean isDefault()
	{
		return isDefault;
	}
	public void setDefault(boolean isDefault)
	{
		this.isDefault = isDefault;
	}

	public boolean isDummy()
	{
		return isDummy;
	}
	public void setDummy(boolean isDummy)
	{
		this.isDummy = isDummy;
	}
	
	public boolean isPiece()
	{
		return isPiece;
	}
	public void setPiece(boolean isPiece)
	{
		this.isPiece = isPiece;
	}
	
	public static ArrayList<Unit> readAllUnits()
	{
		if(unitCache == null)
		{
			try
			{				
				Connection conn = DatabaseHandler.getInstance().getConnection();
				
				if(conn == null)
					Start.exitWithError(Settings.languageBlock.get("dbCouldNotConnect"));
				
				PreparedStatement preparedStmt = null;
		
				String query = "SELECT * FROM units";
				
				preparedStmt = conn.prepareStatement(query);
				
				Miscellaneous.logEvent(preparedStmt.toString(), 5);
				
		        ResultSet res = preparedStmt.executeQuery();
		        
				unitCache = new ArrayList<Unit>();
				
		        while (res.next())
		        {
		        	Unit u = new Unit();
		        	
		        	u.setId(res.getLong("id"));
		        	u.setName(res.getString("name"));
		        	u.setAbbreviation(res.getString("abbreviation"));
		        	u.setDefault(res.getInt("isDefault") == 1);
		        	u.setDummy(res.getInt("isDummy") == 1);
		        	u.setPiece(res.getInt("isPiece") == 1);
		        	
		        	unitCache.add(u);
		        }
		        
		        res.close();
				preparedStmt.close();
			}
			catch(Exception e)
			{
				Start.exitWithError(Settings.languageBlock.get("dbCouldNotConnect"));
			}
		}
	        		
        return unitCache;
	}
	
	@Override
	public boolean equals(Object obj)
	{
		return ((Unit)obj).getName().equalsIgnoreCase(getName());
	}
	
	public static Unit getByName(String unitName)
	{
		if(StringUtils.isEmpty(unitName))
		{
			for(Unit u : readAllUnits())
			{
				if(u.isDummy())
					return u;
			}
			return null;
		}
		
		for(Unit u : readAllUnits())
		{
			for(String unitSynonym : u.getName().split(";"))
			{
				if(unitSynonym.equalsIgnoreCase(unitName))
					return u;
				else if(unitSynonym.equalsIgnoreCase(unitName.replace("-", " ")))
					return u;
			}
		}
		
		return null;
	}
	
	@Override
	public String toString()
	{
		if(getName().contains(";"))
			return getName().split(";")[0];
		else
			return getName();
	}
	
	public static Unit getById(long id)
	{
		for(Unit u : readAllUnits())
		{
			if(u.getId() == id)
				return u;
		}
		
		return null;
	}
	
	public boolean create()
	{
		String query = "INSERT INTO units (name, abbreviation, isDefault, isDummy, isPiece) VALUES (?, ?, ?, ?, ?)";
		Connection conn = DatabaseHandler.getInstance().getConnection();
		PreparedStatement preparedStmt = null;
		try
		{
			preparedStmt = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
		    
			preparedStmt.setString(1, this.getName());
			preparedStmt.setString(2, this.getAbbreviation());
			if(this.isDefault)
				preparedStmt.setInt(3, 1);
			else
				preparedStmt.setInt(3, 0);

			if(this.isDummy)
				preparedStmt.setInt(4, 1);
			else
				preparedStmt.setInt(4, 0);

			if(this.isPiece)
				preparedStmt.setInt(5, 1);
			else
				preparedStmt.setInt(5, 0);
		    
		    preparedStmt.executeUpdate();
		    ResultSet rs = preparedStmt.getGeneratedKeys();
		    if (rs.next())
		    {
		    	this.setId(rs.getInt(1));
		    	Miscellaneous.logEvent("INSERT-ID: " + String.valueOf(this.getId()), 5);

				rs.close();
				preparedStmt.close();
		    	
		    	Miscellaneous.logEvent("Unit has been successfully created.", 2);
		
		    	return true;
		    }
		    else
		    {
		    	rs.close();
		    	String error = "Insert new unit failed.";
		    	Miscellaneous.logEvent(error, 1);
		    }
		}
		catch (SQLException e)
		{
			Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1);
		}
		finally
		{
			try
			{
				if(preparedStmt != null && !preparedStmt.isClosed())
					preparedStmt.close();
			}
			catch (SQLException e)
			{
			}
		}
	      
		return false;
	}
	
	public static Unit getDefaultUnit()
	{
		for(Unit u : readAllUnits())
		{
			if(u.isDefault())
				return u;
		}
		
		return null;
	}
	
	public static Unit getPieceUnit()
	{
		for(Unit u : readAllUnits())
		{
			if(u.isPiece())
				return u;
		}
		
		return null;
	}
}