package org.ambraproject.wombat.config.site;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import org.ambraproject.wombat.config.RuntimeConfigurationException;
import org.ambraproject.wombat.config.site.url.SiteRequestScheme;
import org.ambraproject.wombat.config.theme.Theme;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

public class Site {

  private final String key;
  private final Theme theme;
  private final String journalKey;
  private final String journalName;
  private final SiteRequestScheme requestScheme;

  public Site(String key, Theme theme, SiteRequestScheme requestScheme) {
    this.key = Preconditions.checkNotNull(key);
    this.theme = Preconditions.checkNotNull(theme);
    this.requestScheme = Preconditions.checkNotNull(requestScheme);
    this.journalKey = findJournalKey(theme);
    this.journalName = findJournalName(theme);
  }

  private static final Logger log = LoggerFactory.getLogger(Site.class);

  @VisibleForTesting
  public static final String JOURNAL_KEY_PATH = "journal";
  @VisibleForTesting
  public static final String CONFIG_KEY_FOR_JOURNAL = "journalKey";
  @VisibleForTesting
  public static final String JOURNAL_NAME = "journalName";

  private static String findJournalKey(Theme theme) {
    String journalKey;
    try {
      journalKey = (String) theme.getConfigMap(JOURNAL_KEY_PATH).get(CONFIG_KEY_FOR_JOURNAL);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    if (Strings.isNullOrEmpty(journalKey)) {
      String message = String.format("The theme %s must provide or inherit a journal key at the path: config/%s",
          theme.getKey(), JOURNAL_KEY_PATH);
      throw new RuntimeConfigurationException(message);
    }
    return journalKey;
  }

  private static String findJournalName(Theme theme) {
    String journalName;
    try {
      journalName = (String) theme.getConfigMap(JOURNAL_KEY_PATH).get(JOURNAL_NAME);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    if (Strings.isNullOrEmpty(journalName)) {
      String message = String.format("The theme %s did not provide or inherit a journal name at the path: config/%s",
          theme.getKey(), JOURNAL_KEY_PATH);
      log.error(message);
    }
    return journalName;
  }

  public String getJournalName() { return journalName; }

  public String getKey() {
    return key;
  }

  public Theme getTheme() {
    return theme;
  }

  public String getJournalKey() {
    return journalKey;
  }

  public SiteRequestScheme getRequestScheme() {
    return requestScheme;
  }

  @Override
  public String toString() {
    return getKey();
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Site site = (Site) o;

    if (!key.equals(site.key)) return false;
    if (!theme.equals(site.theme)) return false;
    if (!journalKey.equals(site.journalKey)) return false;
    if (!requestScheme.equals(site.requestScheme)) return false;

    return true;
  }

  @Override
  public int hashCode() {
    int result = key.hashCode();
    result = 31 * result + theme.hashCode();
    result = 31 * result + journalKey.hashCode();
    result = 31 * result + requestScheme.hashCode();
    return result;
  }

}

@@ -526,24 +526,74 @@
 heme theme;%0A
+  private final SiteRequestScheme requestScheme;%0A%0A
   private fi
@@ -654,57 +654,8 @@
 ame;
-%0A  private final SiteRequestScheme requestScheme;
 %0A%0A  
@@ -890,24 +890,25 @@
 estScheme);%0A
+%0A
     this.jou
@@ -2415,16 +2415,20 @@
 Name() %7B
+%0A   
  return 
@@ -2439,16 +2439,18 @@
 nalName;
+%0A 
  %7D%0A%0A  pu
@@ -3021,67 +3021,8 @@
 se;%0A
-    if (!journalKey.equals(site.journalKey)) return false;%0A
     
@@ -3111,43 +3111,121 @@
 %0A%0A  
-@Override%0A  public int hashCode() %7B
+private transient int hashValue;%0A%0A  @Override%0A  public int hashCode() %7B%0A    if (hashValue != 0) return hashValue;
 %0A   
@@ -3303,58 +3303,8 @@
 ();%0A
-    result = 31 * result + journalKey.hashCode();%0A
     
@@ -3362,16 +3362,28 @@
   return
+ hashValue =
  result;

Optimize Site.hashCode()