package ch.qos.logback.core.rolling;

import java.util.Date;

import ch.qos.logback.core.rolling.helper.ArchiveRemover;
import ch.qos.logback.core.rolling.helper.DateTokenConverter;
import ch.qos.logback.core.rolling.helper.RollingCalendar;
import ch.qos.logback.core.spi.ContextAwareBase;

abstract public class TimeBasedFileNamingAndTriggeringPolicyBase<E> extends ContextAwareBase
    implements TimeBasedFileNamingAndTriggeringPolicy<E> {

  protected TimeBasedRollingPolicy<E> tbrp;
  
  protected ArchiveRemover archiveRemover = null;
  protected String elapsedPeriodsFileName;
  protected RollingCalendar rc;
  
  
  protected long currentTime;
  //indicate whether the time has been forced or not
  protected boolean isTimeForced = false;
  protected Date dateInCurrentPeriod = null;
  
  protected long nextCheck;
  protected boolean started = false;

  
  public boolean isStarted() {
    return started;
  }

  public void start() {
    DateTokenConverter dtc = tbrp.fileNamePattern.getDateTokenConverter();
    if (dtc == null) {
      throw new IllegalStateException("FileNamePattern ["
          + tbrp.fileNamePattern.getPattern()
          + "] does not contain a valid DateToken");
    }

    rc = new RollingCalendar();
    rc.init(dtc.getDatePattern());
    addInfo("The date pattern is '" + dtc.getDatePattern()
        + "' from file name pattern '" + tbrp.fileNamePattern.getPattern()
        + "'.");
    rc.printPeriodicity(this);

    // dateInCurrentPeriod can be set by test classes
    // if it has not been set, we set it here
    if (dateInCurrentPeriod == null) {
      dateInCurrentPeriod = new Date();
      updateDateInCurrentPeriod(getCurrentTime());
    }
    computeNextCheck();
  }
  
  public void stop() {
    started = false;
  }
  
  protected void computeNextCheck() {
    nextCheck = rc.getNextTriggeringMillis(dateInCurrentPeriod);
  }

  // allow Test classes to act on the dateInCurrentPeriod field to simulate old
  // log files needing rollover
  public void setDateInCurrentPeriod(Date _dateInCurrentPeriod) {
    this.dateInCurrentPeriod = _dateInCurrentPeriod;
  }

  public Date getDateInCurrentPeriod() {
    return dateInCurrentPeriod;
  }

  public String getElapsedPeriodsFileName() {
    return elapsedPeriodsFileName;
  }

  public String getCurrentPeriodsFileNameWithoutCompressionSuffix() {
    return tbrp.fileNamePatternWCS.convert(dateInCurrentPeriod);
  }


  protected void updateDateInCurrentPeriod(long now) {
    dateInCurrentPeriod.setTime(now);
  }

  public void setCurrentTime(long timeInMillis) {
    currentTime = timeInMillis;
    isTimeForced = true;
  }

  public long getCurrentTime() {
    // if time is forced return the time set by user
    if (isTimeForced) {
      return currentTime;
    } else {
      return System.currentTimeMillis();
    }
  }
  
  public void setTimeBasedRollingPolicy(TimeBasedRollingPolicy<E> _tbrp) {
    this.tbrp = _tbrp;

  }

  public ArchiveRemover getArchiveRemover() {
    return archiveRemover;
  }

}
