
package de.ivu.elect.presentation.exchange;

import java.io.Serializable;
import java.util.Comparator;
import java.util.Locale;

import javax.annotation.Nullable;

import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.util.CaseAndDiacriticIgnoringComparator;
import de.ivu.elect.util.NullComparator;

public class FileFormatByMessageAndTypeComparator implements Comparator<FileFormat>, Serializable {

  private static final Comparator<Object> NULL_COMPARATOR = NullComparator.NULL_BEFORE_NON_NULL_COMPARATOR;

  private static final long serialVersionUID = 1L;

  private final Messages messages;

  private final Comparator<String> messageAndTypeComparator;

  @Nullable
  private final FileType fileTypePreferred;

  public FileFormatByMessageAndTypeComparator(Locale locale, Messages messages) {
    this(locale, messages, FileType.ALL);
  }

  public FileFormatByMessageAndTypeComparator(Locale locale, Messages messages, @Nullable FileType fileTypePreferred) {
    super();

    this.messages = messages;
    this.messageAndTypeComparator = new CaseAndDiacriticIgnoringComparator(locale);

    this.fileTypePreferred = fileTypePreferred;
  }

  @Override
  public int compare(FileFormat one, FileFormat another) {
    int result;

    result = compareByNull(one, another);
    if (result != 0) {
      return result;
    }

    result = compareByKnownFileExtension(one, another, fileTypePreferred);
    if (result != 0) {
      return result;
    }

    result = compareByMessage(one, another);
    if (result != 0) {
      return result;
    }

    return compareByFileExtension(one, another);
  }

  private int compareByKnownFileExtension(FileFormat one, FileFormat another, FileType fileTypePreferred) {
    if (fileTypePreferred == null || FileType.ALL.equals(fileTypePreferred)) {
      return 0;
    }
    boolean oneHasFileType = fileTypePreferred.equals(one.getFileType());
    boolean anotherHasFileType = fileTypePreferred.equals(another.getFileType());

    if (oneHasFileType && anotherHasFileType) {
      return 0;
    }

    if (!oneHasFileType && !anotherHasFileType) {
      return 0;
    }

    if (oneHasFileType) {
      return -1;
    }
    return 1;
  }

  private int compareByNull(FileFormat one, FileFormat another) {
    return NULL_COMPARATOR.compare(one, another);
  }

  private int compareByMessage(FileFormat format1, FileFormat format2) {
    String message1 = messages.getMessageForMessageKey(format1.getName());
    String message2 = messages.getMessageForMessageKey(format2.getName());

    return messageAndTypeComparator.compare(message1, message2);
  }

  private int compareByFileExtension(FileFormat format1, FileFormat format2) {
    String extension1 = format1.getFileType().getFileExtension();
    String extension2 = format2.getFileType().getFileExtension();

    return messageAndTypeComparator.compare(extension1, extension2);
  }
}
