/*
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 Bull S.A.
 * Contact: jonas-team@objectweb.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas.jtests.beans.relation.cascade;

import java.rmi.RemoteException;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.Vector;

import javax.ejb.CreateException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.objectweb.jonas.common.Log;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

/**
 * Implementation for bean Customer
 * @author Ph Durieux
 */
public abstract class CustomerBean implements EntityBean {

    static protected Logger logger = null;
    private CreditCardHL creditCardHL = null;
    private AddressHL addressHL = null;
    private PhoneHL phoneHL = null;
    private CarHL carHL = null;
    private EntityContext ejbContext = null;

    public Integer ejbCreate(Integer id) throws javax.ejb.CreateException {
        logger.log(BasicLevel.DEBUG, "");
        this.setId(id);
        return null;
    }

    public void ejbPostCreate(Integer id) {
        logger.log(BasicLevel.DEBUG, "");
    }

    public Integer ejbCreateWithAddress(Integer id, AddressDO addr) throws javax.ejb.CreateException {
        logger.log(BasicLevel.DEBUG, "");
        this.setId(id);
        return null;
    }

    public void ejbPostCreateWithAddress(Integer id, AddressDO addr) throws javax.ejb.CreateException {
        logger.log(BasicLevel.DEBUG, "");
        CustomerL myLocalInterface = (CustomerL) ejbContext.getEJBLocalObject();
        AddressL addrl = addressHL.create(addr, myLocalInterface);
        setHomeAddress(addrl);
    }


    // business methods

    public Name getName() {
        logger.log(BasicLevel.DEBUG, "");
        Name name = new Name(getLastName(), getFirstName());
        return name;
    }

    public void setName(Name name) {
        logger.log(BasicLevel.DEBUG, "");
        setLastName(name.getLastName());
        setFirstName(name.getFirstName());
    }

    public void setAddress(String street, String city, String state, String zip) throws CreateException, NamingException {
        logger.log(BasicLevel.DEBUG, "");

        AddressL addr = this.getHomeAddress();

        if (addr == null) {
            addr = addressHL.create(street, city, state, zip);
            setHomeAddress(addr);
        } else {
            // Customer already has an address. Change its fields
            addr.setStreet(street);
            addr.setCity(city);
            addr.setState(state);
            addr.setZip(zip);
        }
    }

    public void setAddress(AddressDO addrValue) throws CreateException, NamingException {
        logger.log(BasicLevel.DEBUG, "");
        String street = addrValue.getStreet();
        String city = addrValue.getCity();
        String state = addrValue.getState();
        String zip = addrValue.getZip();

        setAddress(street, city, state, zip);
    }

    public AddressDO getAddress() {
        logger.log(BasicLevel.DEBUG, "");
        AddressL addrL = this.getHomeAddress();
        if (addrL == null) {
            return null;
        }
        String street = addrL.getStreet();
        String city = addrL.getCity();
        String state = addrL.getState();
        String zip = addrL.getZip();
        AddressDO addrValue = new AddressDO(street, city, state, zip);
        return addrValue;
    }

    public void addPhoneNumber(String number, byte type) throws NamingException, CreateException, RemoteException {
        logger.log(BasicLevel.DEBUG, "");
        PhoneL phone = phoneHL.create(number, type, getName().getLastName());
        Collection phoneNumbers = this.getPhoneNumbers();
        phoneNumbers.add(phone);
    }

    public void addCar(String number, byte type) throws NamingException, CreateException, RemoteException {
        logger.log(BasicLevel.DEBUG, "");
        CarL car = carHL.create(number, type, getName().getLastName());
        Collection cars = this.getCars();
        cars.add(car);
    }

    public void setCreditCard(Date date, String num, String name) throws NamingException, CreateException, RemoteException {
        logger.log(BasicLevel.DEBUG, "");
        CreditCardL cc = creditCardHL.create(date, num, name);
        setCreditCard(cc);
    }

    public void removePhoneNumber(byte typeToRemove) {
        logger.log(BasicLevel.DEBUG, "typeToRemove=" + typeToRemove);

        Collection phoneNumbers = this.getPhoneNumbers();
        Iterator iterator = phoneNumbers.iterator();

        while (iterator.hasNext()) {
            PhoneL phone = (PhoneL) iterator.next();
            if (phone.getType() == typeToRemove) {
                phoneNumbers.remove(phone);
                break;
            }
        }
    }

    public void removeCar(byte typeToRemove) {
        logger.log(BasicLevel.DEBUG, "typeToRemove=" + typeToRemove);

        Collection cars = this.getCars();
        Iterator iterator = cars.iterator();

        while (iterator.hasNext()) {
            CarL car = (CarL) iterator.next();
            if (car.getType() == typeToRemove) {
                cars.remove(car);
                break;
            }
        }
    }

    public void updatePhoneNumber(String number, byte typeToUpdate) {
        logger.log(BasicLevel.DEBUG, "typeToUpdate=" + typeToUpdate);

        Collection phoneNumbers = this.getPhoneNumbers();
        Iterator iterator = phoneNumbers.iterator();
        while (iterator.hasNext()) {
            PhoneL phone = (PhoneL) iterator.next();
            if (phone.getType() == typeToUpdate) {
                phone.setNumber(number);
                break;
            }
        }
    }

    public void accident(String carnumber, String invoicenumber) throws RemoteException, CreateException, NamingException {
        logger.log(BasicLevel.DEBUG, "invoicenumber=" + invoicenumber);

        // retrieve car in the list
        CarL car = null;
        boolean found = false;
        for (Iterator i = getCars().iterator(); i.hasNext();) {
            car = (CarL) i.next();
            if (car.getNumber().equals(carnumber)) {
                found = true;
                break;
            }
        }
        if (! found) {
            throw new RemoteException("Car not found:" + carnumber);
        }
               
        // Create new invoice
        car.addInvoice(invoicenumber);
    }

    public void updateCar(String number, byte typeToUpdate) {
        logger.log(BasicLevel.DEBUG, "typeToUpdate=" + typeToUpdate);

        Collection cars = this.getCars();
        Iterator iterator = cars.iterator();
        while (iterator.hasNext()) {
            CarL car = (CarL) iterator.next();
            if (car.getType() == typeToUpdate) {
                car.setNumber(number);
                break;
            }
        }
    }

    public Vector getPhoneList() {
        logger.log(BasicLevel.DEBUG, "");

        Vector vv = new Vector();
        Collection phoneNumbers = this.getPhoneNumbers();

        Iterator iterator = phoneNumbers.iterator();
        while (iterator.hasNext()) {
            PhoneL phone = (PhoneL) iterator.next();
            String ss = "Type=" + phone.getType() + "  Number=" + phone.getNumber();
            vv.add(ss);
        }
        return vv;
    }

    public Vector getCarList() {
        logger.log(BasicLevel.DEBUG, "");

        Vector vv = new Vector();
        Collection cars = this.getCars();

        Iterator iterator = cars.iterator();
        while (iterator.hasNext()) {
            CarL car = (CarL) iterator.next();
            String ss = "Type=" + car.getType() + "  Number=" + car.getNumber();
            vv.add(ss);
        }
        return vv;
    }

    // persistent relationships

    public abstract AddressL getHomeAddress();
    public abstract void setHomeAddress(AddressL address);

    public abstract CreditCardL getCreditCard();
    public abstract void setCreditCard(CreditCardL card);

    public abstract java.util.Collection getPhoneNumbers();
    public abstract void setPhoneNumbers(java.util.Collection phones);

    public abstract java.util.Collection getCars();
    public abstract void setCars(java.util.Collection cars);

    // abstract accessor methods
    public abstract Integer getId();
    public abstract void setId(Integer id);
 
    public abstract String getLastName( );
    public abstract void setLastName(String lname);

    public abstract String getFirstName( );
    public abstract void setFirstName(String fname);

    // standard call back methods

    public void setEntityContext(EntityContext ec) {
        if (logger == null)
            logger = Log.getLogger(Log.JONAS_TESTS_PREFIX);
        logger.log(BasicLevel.DEBUG, "");
        try {
            ejbContext = ec;
            InitialContext cntx = new InitialContext();
            creditCardHL = (CreditCardHL) cntx.lookup("java:comp/env/ejb/CreditCardHomeLocal");
            addressHL = (AddressHL) cntx.lookup("java:comp/env/ejb/AddressHomeLocal");
            phoneHL = (PhoneHL) cntx.lookup("java:comp/env/ejb/PhoneHomeLocal");
            carHL = (CarHL) cntx.lookup("java:comp/env/ejb/CarHomeLocal");
        } catch (Exception e) {
            throw new javax.ejb.EJBException(e);
        }
    }

    public void unsetEntityContext() { 
        logger.log(BasicLevel.DEBUG, "");
        ejbContext = null;
    }

    public void ejbLoad() { 
        logger.log(BasicLevel.DEBUG, "");
        checkCMRAccess();
    }

    public void ejbStore() { 
        logger.log(BasicLevel.DEBUG, "");
        checkCMRAccess();
    }

    public void ejbActivate() { 
        logger.log(BasicLevel.DEBUG, "");
    }

    public void ejbPassivate() { 
        logger.log(BasicLevel.DEBUG, "");
    }

    public void ejbRemove() throws javax.ejb.RemoveException {
        logger.log(BasicLevel.DEBUG, "");
        checkCMRAccess();
    }

    protected void checkCMRAccess() {
        logger.log(BasicLevel.DEBUG, "");
        Collection col = getCars();
    }
}
