package org.eclipse.osbp.runtime.web.sample.dtos.mapper;

import org.eclipse.osbp.dsl.dto.lib.MappingContext;
import org.eclipse.osbp.runtime.web.sample.dtos.AddressDto;
import org.eclipse.osbp.runtime.web.sample.dtos.CountryDto;
import org.eclipse.osbp.runtime.web.sample.dtos.mapper.BaseUUIDDtoMapper;
import org.eclipse.osbp.runtime.web.sample.entities.Address;
import org.eclipse.osbp.runtime.web.sample.entities.Country;

/**
 * This class maps the dto {@link AddressDto} to and from the entity {@link Address}.
 * 
 */
@SuppressWarnings("all")
public class AddressDtoMapper<DTO extends AddressDto, ENTITY extends Address> extends BaseUUIDDtoMapper<DTO, ENTITY> {
  /**
   * Creates a new instance of the entity
   */
  public Address createEntity() {
    return new Address();
  }
  
  /**
   * Creates a new instance of the dto
   */
  public AddressDto createDto() {
    return new AddressDto();
  }
  
  /**
   * Maps the entity {@link Address} to the dto {@link AddressDto}.
   * 
   * @param dto - The target dto
   * @param entity - The source entity
   * @param context - The context to get information about depth,...
   * 
   */
  public void mapToDTO(final AddressDto dto, final Address entity, final MappingContext context) {
    if(context == null){
    	throw new IllegalArgumentException("Please pass a context!");
    }
    context.register(createDtoHash(entity), dto);
    
    super.mapToDTO(dto, entity, context);
    
    dto.setStreet(toDto_street(entity, context));
    dto.setCity(toDto_city(entity, context));
    dto.setCountry(toDto_country(entity, context));
  }
  
  /**
   * Maps the dto {@link AddressDto} to the entity {@link Address}.
   * 
   * @param dto - The source dto
   * @param entity - The target entity
   * @param context - The context to get information about depth,...
   * 
   */
  public void mapToEntity(final AddressDto dto, final Address entity, final MappingContext context) {
    if(context == null){
    	throw new IllegalArgumentException("Please pass a context!");
    }
    
    context.register(createEntityHash(dto), entity);
    context.registerMappingRoot(createEntityHash(dto), dto);
    super.mapToEntity(dto, entity, context);
    
    entity.setStreet(toEntity_street(dto, entity, context));
    entity.setCity(toEntity_city(dto, entity, context));
    entity.setCountry(toEntity_country(dto, entity, context));
  }
  
  /**
   * Maps the property street from the given entity to dto property.
   * 
   * @param in - The source entity
   * @param context - The context to get information about depth,...
   * @return the mapped value
   * 
   */
  protected String toDto_street(final Address in, final MappingContext context) {
    return in.getStreet();
  }
  
  /**
   * Maps the property street from the given entity to dto property.
   * 
   * @param in - The source entity
   * @param parentEntity - The parentEntity
   * @param context - The context to get information about depth,...
   * @return the mapped value
   * 
   */
  protected String toEntity_street(final AddressDto in, final Address parentEntity, final MappingContext context) {
    return in.getStreet();
  }
  
  /**
   * Maps the property city from the given entity to dto property.
   * 
   * @param in - The source entity
   * @param context - The context to get information about depth,...
   * @return the mapped value
   * 
   */
  protected String toDto_city(final Address in, final MappingContext context) {
    return in.getCity();
  }
  
  /**
   * Maps the property city from the given entity to dto property.
   * 
   * @param in - The source entity
   * @param parentEntity - The parentEntity
   * @param context - The context to get information about depth,...
   * @return the mapped value
   * 
   */
  protected String toEntity_city(final AddressDto in, final Address parentEntity, final MappingContext context) {
    return in.getCity();
  }
  
  /**
   * Maps the property country from the given entity to the dto.
   * 
   * @param in - The source entity
   * @param context - The context to get information about depth,...
   * @return the mapped dto
   * 
   */
  protected CountryDto toDto_country(final Address in, final MappingContext context) {
    if(in.getCountry() != null) {
    	// find a mapper that knows how to map the concrete input type.
    	org.eclipse.osbp.dsl.dto.lib.IMapper<CountryDto, Country> mapper = (org.eclipse.osbp.dsl.dto.lib.IMapper<CountryDto, Country>) getToDtoMapper(CountryDto.class, in.getCountry().getClass());
    	if(mapper == null) {
    		throw new IllegalStateException("Mapper must not be null!");
    	}
    	CountryDto dto = null;
    	dto = context.get(mapper.createDtoHash(in.getCountry()));
    	if(dto != null) {
    		if(context.isRefresh()){
    			mapper.mapToDTO(dto, in.getCountry(), context);
    		}
    		return dto;
    	}
    	
    	context.increaseLevel();
    	dto = mapper.createDto();
    	mapper.mapToDTO(dto, in.getCountry(), context);
    	context.decreaseLevel();
    	return dto;
    } else {
    	return null;
    }
  }
  
  /**
   * Maps the property country from the given dto to the entity.
   * 
   * @param in - The source dto
   * @param parentEntity - The parent entity
   * @param context - The context to get information about depth,...
   * @return the mapped entity
   * 
   */
  protected Country toEntity_country(final AddressDto in, final Address parentEntity, final MappingContext context) {
    if(in.getCountry() != null) {
    	// find a mapper that knows how to map the concrete input type.
    	org.eclipse.osbp.dsl.dto.lib.IMapper<CountryDto, Country> mapper = (org.eclipse.osbp.dsl.dto.lib.IMapper<CountryDto, Country>) getToEntityMapper(in.getCountry().getClass(), Country.class);
    	if(mapper == null) {
    		throw new IllegalStateException("Mapper must not be null!");
    	}
    
    	Country entity = null;
    	entity = context.get(mapper.createEntityHash(in.getCountry()));
    	if(entity != null) {
    		return entity;
    	} else {
    		entity = (Country) context
    			.findEntityByEntityManager(Country.class, in.getCountry().getUuid());
    		if (entity != null) {
    			context.register(mapper.createEntityHash(in.getCountry()), entity);
    			return entity;
    		}
    	}
    
    	entity = mapper.createEntity();
    	mapper.mapToEntity(in.getCountry(), entity, context);	
    	return entity;
    } else {
    	return null;
    }	
  }
  
  public String createDtoHash(final Object in) {
    return org.eclipse.osbp.runtime.common.hash.HashUtil.createObjectWithIdHash(AddressDto.class, in);
  }
  
  public String createEntityHash(final Object in) {
    return org.eclipse.osbp.runtime.common.hash.HashUtil.createObjectWithIdHash(Address.class, in);
  }
}
