package performa.orm;

import java.util.Set;
import oneit.logging.LoggingArea;
import oneit.objstore.rdbms.filters.EqualsFilter;
import oneit.objstore.rdbms.filters.IsNotNullFilter;
import oneit.utils.BusinessException;
import oneit.utils.CollectionUtils;
import oneit.utils.StringUtils;
import oneit.utils.filter.Filter;
import oneit.utils.math.NullArith;
import performa.orm.types.JobStatus;
import performa.orm.types.TimeZone;
import performa.utils.Utils;


public class Company extends BaseCompany
{
    private static final long serialVersionUID = 0L;
    
    public  static LoggingArea  LOG = LoggingArea.createLoggingArea("Company");

    // This constructor should not be called
    public Company ()
    {
        // Do not add any code to this, always put it in initialiseNewObject
    }

    @Override
    protected void postInitNewObj() throws BusinessException 
    {
        addToHiringTeams(HiringTeam.createHiringTeam(getTransaction()));

        super.postInitNewObj();
    }
    
    
    public boolean showHasClientSupport()
    {
        return isTrue(getHasClientSupport());
    }
    
    public boolean showTeamManagesOwnBilling()
    {
        return isTrue(getManageOwnBilling());
    }
    
    
    @Override
    public String getToString() 
    {
        return StringUtils.subNulls(getCompanyName(), super.getToString());
    }
    
    
    public PaymentPlan getSelectedPaymentPlan()
    {
        if(getPaymentJobCount() != null)
        {
            PaymentPlan maxPlan =   Utils.getMaximumPaymentPlan(getTransaction());
            
            if(maxPlan!=null && getPaymentJobCount()>=maxPlan.getActiveJobCount())
            {
                return maxPlan;
            }
            
            PaymentPlan[]   plans   =   PaymentPlan.SearchByAll()
                                                .andActiveJobCount(new EqualsFilter<>(getPaymentJobCount()))
                                                .search(getTransaction());
            
            if(plans.length > 0)
            {
                return plans[0];
            }
        }
        
        return null;
    }
    
    
    public Double getPaymentPlanAmount()
    {
        PaymentPlan selectedPaymentPlan =   getSelectedPaymentPlan();
        
        if(selectedPaymentPlan!=null)
        {
            return selectedPaymentPlan.getAmount();
        }
        
        return null;
    }
   
    
    public Double getPerJobPaymentPlanAmount()
    {
        PaymentPlan selectedPaymentPlan =   getSelectedPaymentPlan();
        
        if(selectedPaymentPlan!=null)
        {
            return NullArith.divide(selectedPaymentPlan.getAmount(), selectedPaymentPlan.getActiveJobCount());
        }
        
        return null;
    }
    
    
    public Double getPaymentPlanSaveAmount()
    {
        PaymentPlan selectedPaymentPlan =   getSelectedPaymentPlan();
        
        if(selectedPaymentPlan!=null)
        {
            return selectedPaymentPlan.getPerMonthSaveAmount();
        }
        
        return null;
    }
    
    
    public boolean canCreateJob()
    {        
        return getPaymentPlan() != null && getPaymentPlan().getActiveJobCount() > getUsedCredits();
    }

    
    @Override
    public Integer getUsedCredits() 
    {
        return super.getUsedCredits()  != null ? super.getUsedCredits() : 0;
    }

    
    public Job[] getOpenJobs()
    {
        return  Job.SearchByCompany()
                    .andJobStatus(new EqualsFilter<>(JobStatus.OPEN))
                    .byCompany(this)
                    .search(getTransaction());
    }
    
    
    public Integer getOpenJobsCount()
    {
        return getOpenJobs().length;
    }

    
    public Boolean isSubscriptionChanged()
    {
        PaymentPlan selectedPaymentPlan =   getSelectedPaymentPlan();
        
        if(selectedPaymentPlan!=null)
        {    
            Company earliestBackup  =   (Company) getEarliestBackup();
            
            if(!CollectionUtils.equals(earliestBackup.getPaymentPlan(), selectedPaymentPlan))
            {
                return Boolean.TRUE;
            }
        }
        
        return Boolean.FALSE;
    }
    
    public HiringTeam getDefaultHiringTeam()
    {
        return getHiringTeamsCount() > 0 ? getHiringTeamsAt(0) : null;
    }
    
    public Set<HiringTeam> getBillingTeams()
    {
        Filter<HiringTeam>  filter  =   HiringTeam.SearchByBillingTeams()
                                                    .andCardID(new IsNotNullFilter<>())
                                                    .andManageOwnBilling(new EqualsFilter<>(Boolean.TRUE));
                    
        return pipelineCompany().toHiringTeams(filter).uniqueVals();
    }
    
    public TimeZone getDefaultTimeZone()
    {
        return pipelineCompany().toHiringTeams().toTimeZone().val();
    }
}