package com.utopiaindustries.util;


import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class TimePeriodFormatter {
    private LocalDateTime from;
    private LocalDateTime to;
    private long seconds;
    private long minutes;
    private long hours;
    private long days;
    private long months;
    private long years;
    private final String separator = ", ";
    private final String lastSeparator = " and ";

    /**
     * constructor
     */
    public TimePeriodFormatter() {}

    /**
     * from
     */
    public TimePeriodFormatter from( LocalDateTime from ) {
        this.from = from;
        return this;
    }

    /**
     * to
     */
    public TimePeriodFormatter to( LocalDateTime to ) {
        this.to = to;
        // calculate seconds, minutes, hours, days, months and years
        this.calculateAll();
        return this;
    }

    /**
     * calculate seconds, minutes, hours, days, months and years
     */
    private void calculateAll() {
        this.calculateSeconds();
        this.calculateMinutes();
        this.calculateHours();
        this.calculateDays();
        this.calculateMonths();
        this.calculateYears();
    }

    /**
     * calculate seconds
     */
    private void calculateSeconds() {
        this.seconds = ChronoUnit.SECONDS.between( this.from, this.to ) % 60;
    }

    /**
     * calculate minutes
     */
    private void calculateMinutes() {
        this.minutes = ChronoUnit.MINUTES.between( this.from, this.to ) % 60;
    }

    /**
     * calculate hours
     */
    private void calculateHours() {
        this.hours = ChronoUnit.HOURS.between( this.from, this.to ) % 24;
    }

    /**
     * calculate days
     */
    private void calculateDays() {
        this.days = ChronoUnit.DAYS.between( this.from, this.to ) % 30;
    }

    /**
     * calculate months
     */
    private void calculateMonths() {
        this.months = ChronoUnit.MONTHS.between( this.from, this.to ) % 12;
    }

    /**
     * calculate years
     */
    private void calculateYears() {
        this.years = ChronoUnit.YEARS.between( this.from, this.to );
    }

    /**
     * format human readable string
     */
    public String format() {
        StringBuilder stringBuilder = new StringBuilder();
        // years
        if ( this.years > 0 ) {
            stringBuilder.append( String.format( "%s %s", this.years, ( this.years == 1 ? "year" : "years" ) ) );
            stringBuilder.append( this.separator );
        }
        // months
        if ( this.months > 0 ) {
            stringBuilder.append( String.format( "%s %s", this.months, ( this.months == 1 ? "month" : "months" ) ) );
            stringBuilder.append( this.separator );
        }
        // days
        if ( this.days > 0 ) {
            stringBuilder.append( String.format( "%s %s", this.days, ( this.days == 1 ? "day" : "days" ) ) );
            stringBuilder.append( this.separator );
        }
        // hours
        if ( this.hours > 0 ) {
            stringBuilder.append( String.format( "%s %s", this.hours, ( this.hours == 1 ? "hour" : "hours" ) ) );
            stringBuilder.append( this.separator );
        }
        // minutes
        if ( this.minutes > 0 ) {
            stringBuilder.append( String.format( "%s %s", this.minutes, ( this.minutes == 1 ? "minute" : "minutes" ) ) );
            stringBuilder.append( this.separator );
        }
        // seconds
        if ( this.seconds > 0 ) {
            stringBuilder.append( String.format( "%s %s", this.seconds, ( this.seconds == 1 ? "second" : "seconds" ) ) );
        }
        // format
        String formattedPeriod = stringBuilder.toString();
        // remove ending comma and space
        if ( formattedPeriod.endsWith( this.separator ) ) {
            formattedPeriod = formattedPeriod.substring( 0, formattedPeriod.lastIndexOf( this.separator ) );
        }
        // replace last instance of ", " with "and"
        formattedPeriod = StringUtils.replaceLast( formattedPeriod, separator, lastSeparator );
        return formattedPeriod;
    }
}