using System;
using System.Collections;
using System.Xml;
using System.Data.OleDb;
using System.Data.SqlClient;
using banco1.persistencia;

namespace banco1.domain
{
	/// <summary>
	/// Representa un producto bancario genérico, como una cuenta, una tarjeta, un préstamo, etc.
	/// </summary>
	public abstract class Producto
	{
		protected static String mEntidad="1000";
		protected String mSucursal, mCCC;  // mDC
		protected ArrayList mMovimientos, mTitulares;
		protected bool mActivo;
		protected DateTime mFechaDeCreacion, mFechaDeCancelacion;

		public Producto() 
		{
		}

		public Producto(String sucursal) 
		{
			this.mSucursal=sucursal;
			this.mCCC=getCCCSiguiente(sucursal);
			this.mFechaDeCreacion=DateTime.Now;
			insert();
			actualizaCCCSiguiente(sucursal, mCCC);
			mTitulares=new ArrayList();
		}

		public Producto(String sucursal, String ccc)
		{
			String SQL="Select Activo, FechaDeCreacion, FechaDeCancelacion " +
					"from Productos where Sucursal=? and CCC=?";
			OleDbCommand cmd = new OleDbCommand(SQL);
			cmd.Parameters.Add("", OleDbType.VarChar).Value=sucursal;
			cmd.Parameters.Add("", OleDbType.VarChar).Value=ccc;
			cmd.Connection = Broker.getBD();
			OleDbDataReader r=cmd.ExecuteReader();
			if (r.Read()) 
			{
				mSucursal=sucursal;
				mCCC=ccc;
				mActivo=r.GetBoolean(0);
				mFechaDeCreacion=r.GetDateTime(1);
				if (!r.IsDBNull(2))
					mFechaDeCancelacion=r.GetDateTime(2);
				mMovimientos=new ArrayList();
				mTitulares=new ArrayList();
				cargaTitulares();
			}
			cmd.Connection.Close();
		}

		public void cargaTitulares() 
		{
			mTitulares=new ArrayList();
			String SQL="Select NIF from Contratos where Sucursal=? and CCC=?";
			OleDbCommand cmd = new OleDbCommand(SQL);
			cmd.Parameters.Add("", OleDbType.VarChar).Value=sucursal;
			cmd.Parameters.Add("", OleDbType.VarChar).Value=ccc;
			cmd.Connection = Broker.getBD();
			OleDbDataReader r=cmd.ExecuteReader();
			while (r.Read()) 
			{
				String nif=r.GetString(0);
				Cliente c=new Cliente(nif);
				mTitulares.Add(c);
			}
			cmd.Connection.Close();
		}

		protected String getCCCSiguiente(String sucursal) 
		{
			String SQL="Select UltimoCCC from Ultimos where Sucursal=?";
			OleDbCommand cmd=Broker.getCommand(SQL);
			cmd.Parameters.Add("[sucursal]", OleDbType.VarChar).Value=sucursal;
			OleDbDataReader r=cmd.ExecuteReader();
			String ultimoCCC="";
			if (r.Read()) 
			{
				ultimoCCC=r.GetString(0);
				double dUltimo=double.Parse(ultimoCCC)+1;
				ultimoCCC=""+dUltimo; 
				int longitud=ultimoCCC.Length;
				for (int i=0; i<10-longitud; i++) 
				{
					ultimoCCC="0" + ultimoCCC;
				}
				cmd.Connection.Close();
				return ultimoCCC;
			} else throw new Exception("Error en Producto::getCCCSiguiente(String)");
		}

		protected void actualizaCCCSiguiente(String sucursal, String ultimoCCC) 
		{
			String SQL="Update Ultimos set UltimoCCC=? where Sucursal=?";
			OleDbCommand cmd=Broker.getCommand(SQL);
			cmd.Parameters.Add("[ultimo]", OleDbType.VarChar).Value=ultimoCCC;
			cmd.Parameters.Add("[sucursal]", OleDbType.VarChar).Value=sucursal;
			cmd.ExecuteNonQuery();
		}

		public virtual void insert() 
		{
			String SQL="Insert into Productos " +
				"(Sucursal, CCC, Activo, FechaDeCreacion) values (?, ?, ?, ?)";
			OleDbCommand cmd = Broker.getCommand(SQL);
			cmd.Parameters.Add("", OleDbType.VarChar).Value=this.mSucursal;
			cmd.Parameters.Add("", OleDbType.VarChar).Value=this.mCCC;
			cmd.Parameters.Add("", OleDbType.Boolean).Value=this.mActivo;
			cmd.Parameters.Add("", OleDbType.Date).Value=this.mFechaDeCreacion;
			cmd.ExecuteNonQuery();
			cmd.Connection.Close();
		}

		public void update() 
		{
			String SQL="Update Productos set Activo=?, FechaDeCancelacion=? " +
				"where Sucursal=? and CCC=?";
			OleDbCommand cmd = new OleDbCommand(SQL);
			cmd.Parameters.Add("", OleDbType.Boolean).Value=this.mActivo;
			cmd.Parameters.Add("", OleDbType.Date).Value=this.mFechaDeCancelacion;
			cmd.Parameters.Add("", OleDbType.VarChar).Value=this.mSucursal;
			cmd.Parameters.Add("", OleDbType.VarChar).Value=this.mCCC;
			cmd.Connection = Broker.getBD();
			cmd.ExecuteNonQuery();
			cmd.Connection.Close();			
		}

		public static String entidad 
		{
			get { return mEntidad; }
		}

		public String sucursal
		{
			get { return mSucursal; }
		}

		public String ccc 
		{
			get { return mCCC; }
		}

		public String digitoDeControl
		{
			get 
			{ 
				return getDigitoDeControl(mSucursal, mCCC);
			}
		}

		public String numero 
		{
			get { return Cuenta.entidad + this.sucursal + this.digitoDeControl + this.ccc; }
		}

		public static String getDigitoDeControl(String sucursal, String ccc) 
		{
			if (sucursal.Equals("")) sucursal="0";
			if (ccc.Equals("")) ccc="0";
			int e=int.Parse(mEntidad);
			int s=int.Parse(sucursal);
			int iccc=int.Parse(ccc);
			int dc=(e+s+iccc) % 25;
			String result=""+dc;
			if (result.Length==1) 
				result="0" + result;
			return result;
		}        

		public void add(Cliente c) 
		{
			if (yaEsTitular(c))
				throw new Exception("El cliente con NIF " + c.nif + " ya es titular de este producto");
			else 
			{
				Contrato con=new Contrato(c, this);
				con.insert();
			}
		}

		public bool yaEsTitular(Cliente c) 
		{
			String SQL="Select count(*) from Contratos where NIF=? and " +
				"Sucursal=? and CCC=?";
			OleDbCommand cmd=Broker.getCommand(SQL);
			cmd.Parameters.Add("", OleDbType.VarChar).Value=c.nif;
			cmd.Parameters.Add("", OleDbType.VarChar).Value=this.mSucursal;
			cmd.Parameters.Add("", OleDbType.VarChar).Value=this.mCCC;
			OleDbDataReader r=cmd.ExecuteReader();
			int result=0;
			if (r.Read()) 
			{
				result=r.GetInt32(0);
			} 
			cmd.Connection.Close();
			return result==1;
		}

		public ArrayList titulares 
		{
			get { return this.mTitulares; }
		}

		public ArrayList movimientos 
		{
			get { return this.mMovimientos; }
		}

		/******* Otras operaciones ********/
		public abstract bool esCancelable();

		public bool estaActivo() 
		{
			return mActivo;
		}

		public void bloquear() 
		{
			mActivo=false;
			update();
		}

		public void desbloquear() 
		{
			mActivo=true;
			update();
		}

		public void cancelar() 
		{
			this.mFechaDeCancelacion=System.DateTime.Now;
			mActivo=false;
			update();
		}

		public bool cancelado 
		{
			get { return mFechaDeCancelacion.Year>2000; }
		}

		public void cargaMovimientos() 
		{
			String SQL="Select Id from Movimientos " +
				"where Sucursal=? and CCC=?";
			OleDbCommand cmd = new OleDbCommand(SQL);
			cmd.Parameters.Add("", OleDbType.VarChar).Value=sucursal;
			cmd.Parameters.Add("", OleDbType.VarChar).Value=ccc;
			cmd.Connection = Broker.getBD();
			OleDbDataReader r=cmd.ExecuteReader();
			while (r.Read()) 
			{
				Movimiento m=new Movimiento(r.GetInt32(0));
				this.mMovimientos.Add(m);
			}
			cmd.Connection.Close();
		}
	}
}
