package org.eclipse.osbp.dsl.tests.carstore.dtos;

import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import javax.validation.Valid;
import org.eclipse.osbp.dsl.common.datatypes.IDto;
import org.eclipse.osbp.dsl.tests.carstore.dtos.AddressDto;
import org.eclipse.osbp.dsl.tests.carstore.dtos.BaseDto;
import org.eclipse.osbp.dsl.tests.carstore.dtos.CarDto;
import org.eclipse.osbp.runtime.common.annotations.Dispose;
import org.eclipse.osbp.runtime.common.annotations.DomainReference;
import org.eclipse.osbp.runtime.common.annotations.FilterDepth;

@SuppressWarnings("all")
public class PersonDto extends BaseDto implements IDto, Serializable, PropertyChangeListener {
  private String firstname;
  
  private String lastname;
  
  @DomainReference
  @FilterDepth(depth = 0)
  private List<CarDto> ownsCars;
  
  @Valid
  private AddressDto homeAddress;
  
  @Valid
  private AddressDto workAddress;
  
  public PersonDto() {
    installLazyCollections();
  }
  
  /**
   * Installs lazy collection resolving for entity {@link Person} to the dto {@link PersonDto}.
   * 
   */
  protected void installLazyCollections() {
    super.installLazyCollections();
    ownsCars = new org.eclipse.osbp.dsl.dto.lib.OppositeDtoList<>(
    				org.eclipse.osbp.dsl.dto.lib.MappingContext.getCurrent(),
    				CarDto.class, "owner.uuid",
    				(java.util.function.Supplier<Object> & Serializable) () -> this.getUuid(), this);
  }
  
  /**
   * Checks whether the object is disposed.
   * @throws RuntimeException if the object is disposed.
   */
  private void checkDisposed() {
    if (isDisposed()) {
      throw new RuntimeException("Object already disposed: " + this);
    }
  }
  
  /**
   * Calling dispose will destroy that instance. The internal state will be 
   * set to 'disposed' and methods of that object must not be used anymore. 
   * Each call will result in runtime exceptions.<br/>
   * If this object keeps composition containments, these will be disposed too. 
   * So the whole composition containment tree will be disposed on calling this method.
   */
  @Dispose
  public void dispose() {
    if (isDisposed()) {
      return;
    }
    super.dispose();
  }
  
  /**
   * Returns the firstname property or <code>null</code> if not present.
   */
  public String getFirstname() {
    return this.firstname;
  }
  
  /**
   * Sets the <code>firstname</code> property to this instance.
   * 
   * @param firstname - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setFirstname(final String firstname) {
    firePropertyChange("firstname", this.firstname, this.firstname = firstname );
  }
  
  /**
   * Returns the lastname property or <code>null</code> if not present.
   */
  public String getLastname() {
    return this.lastname;
  }
  
  /**
   * Sets the <code>lastname</code> property to this instance.
   * 
   * @param lastname - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setLastname(final String lastname) {
    firePropertyChange("lastname", this.lastname, this.lastname = lastname );
  }
  
  /**
   * Returns an unmodifiable list of ownsCars.
   */
  public List<CarDto> getOwnsCars() {
    return Collections.unmodifiableList(internalGetOwnsCars());
  }
  
  /**
   * Returns the list of <code>CarDto</code>s thereby lazy initializing it. For internal use only!
   * 
   * @return list - the resulting list
   * 
   */
  public List<CarDto> internalGetOwnsCars() {
    if (this.ownsCars == null) {
      this.ownsCars = new java.util.ArrayList<CarDto>();
    }
    return this.ownsCars;
  }
  
  /**
   * Adds the given carDto to this object. <p>
   * Since the reference is a composition reference, the opposite reference <code>CarDto#owner</code> of the <code>carDto</code> will be handled automatically and no further coding is required to keep them in sync.<p>
   * See {@link CarDto#setOwner(CarDto)}.
   * 
   * @param carDto - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void addToOwnsCars(final CarDto carDto) {
    checkDisposed();
    
    carDto.setOwner(this);
  }
  
  /**
   * Removes the given carDto from this object. <p>
   * 
   * @param carDto - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void removeFromOwnsCars(final CarDto carDto) {
    checkDisposed();
    
    carDto.setOwner(null);
  }
  
  /**
   * For internal use only!
   */
  public void internalAddToOwnsCars(final CarDto carDto) {
    
    if(!internalGetOwnsCars().contains(carDto)) {
    	if(!org.eclipse.osbp.dsl.dto.lib.MappingContext.isMappingMode()) {
    		List<CarDto> oldList = null;
    		if(internalGetOwnsCars() instanceof org.eclipse.osbp.dsl.dto.lib.AbstractOppositeDtoList) {
    			oldList = ((org.eclipse.osbp.dsl.dto.lib.AbstractOppositeDtoList) internalGetOwnsCars()).copy();
    		} else {
    			oldList = new java.util.ArrayList<>(internalGetOwnsCars());
    		}
    		internalGetOwnsCars().add(carDto);
    		firePropertyChange("ownsCars", oldList, internalGetOwnsCars());
    	} else {
    		// in mapping mode, we do NOT resolve any collection
    		internalGetOwnsCars().add(carDto);
    	}
    }
  }
  
  /**
   * For internal use only!
   */
  public void internalRemoveFromOwnsCars(final CarDto carDto) {
    if(!org.eclipse.osbp.dsl.dto.lib.MappingContext.isMappingMode()) {
    	List<CarDto> oldList = null;
    	if(internalGetOwnsCars() instanceof org.eclipse.osbp.dsl.dto.lib.AbstractOppositeDtoList) {
    		oldList = ((org.eclipse.osbp.dsl.dto.lib.AbstractOppositeDtoList) internalGetOwnsCars()).copy();
    	} else {
    		oldList = new java.util.ArrayList<>(internalGetOwnsCars());
    	}
    	internalGetOwnsCars().remove(carDto);
    	firePropertyChange("ownsCars", oldList, internalGetOwnsCars());	
    }else{
    	// in mapping mode, we do NOT resolve any collection
    	internalGetOwnsCars().remove(carDto);
    }
  }
  
  /**
   * Sets the <code>ownsCars</code> property to this instance.
   * Since the reference has an opposite reference, the opposite <code>CarDto#
   * owner</code> of the <code>ownsCars</code> will be handled automatically and no 
   * further coding is required to keep them in sync.<p>
   * See {@link CarDto#setOwner(CarDto)
   * 
   * @param ownsCars - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setOwnsCars(final List<CarDto> ownsCars) {
    checkDisposed();
    for (CarDto dto : internalGetOwnsCars().toArray(new CarDto[this.ownsCars.size()])) {
    	removeFromOwnsCars(dto);
    }
    
    if(ownsCars == null) {
    	return;
    }
    
    for (CarDto dto : ownsCars) {
    	addToOwnsCars(dto);
    }
  }
  
  /**
   * Returns the homeAddress property.
   */
  public AddressDto getHomeAddress() {
    if(this.homeAddress== null){
      this.homeAddress = new AddressDto();
    }
    return this.homeAddress;
  }
  
  /**
   * Sets the <code>homeAddress</code> property to this instance.
   * 
   * @param homeAddress - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setHomeAddress(final AddressDto homeAddress) {
    // ensure that embedded beans will notify their parent about changes
    // so their dirty state can be handled properly
    if (this.homeAddress != null) {
    	this.homeAddress.removePropertyChangeListener(this);
    }
    
    firePropertyChange("homeAddress", this.homeAddress, this.homeAddress = homeAddress );
    
    if (this.homeAddress != null) {
    	this.homeAddress.addPropertyChangeListener(this);
    }
  }
  
  /**
   * Returns the workAddress property.
   */
  public AddressDto getWorkAddress() {
    if(this.workAddress== null){
      this.workAddress = new AddressDto();
    }
    return this.workAddress;
  }
  
  /**
   * Sets the <code>workAddress</code> property to this instance.
   * 
   * @param workAddress - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setWorkAddress(final AddressDto workAddress) {
    // ensure that embedded beans will notify their parent about changes
    // so their dirty state can be handled properly
    if (this.workAddress != null) {
    	this.workAddress.removePropertyChangeListener(this);
    }
    
    firePropertyChange("workAddress", this.workAddress, this.workAddress = workAddress );
    
    if (this.workAddress != null) {
    	this.workAddress.addPropertyChangeListener(this);
    }
  }
  
  public void propertyChange(final java.beans.PropertyChangeEvent event) {
    Object source = event.getSource();
    
    // forward the event from embeddable beans to all listeners. So the parent of the embeddable
    // bean will become notified and its dirty state can be handled properly
    
    
    	if(source == homeAddress){
    		firePropertyChange("homeAddress" + "_" + event.getPropertyName(), event.getOldValue(), event.getNewValue());
    	} else 
    
    
    	if(source == workAddress){
    		firePropertyChange("workAddress" + "_" + event.getPropertyName(), event.getOldValue(), event.getNewValue());
    	} else 
    { 
    	super.propertyChange(event);
    }
  }
}
