package com.timgroup.tucker.info.status;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.timgroup.tucker.info.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.timgroup.tucker.info.Component;
import com.timgroup.tucker.info.Report;
import com.timgroup.tucker.info.component.VersionComponent;

public class StatusPageGenerator {
    
    public static final String DTD_FILENAME = "status-page.dtd";
    public static final String CSS_FILENAME = "status-page.css";

    public static final String COMPONENT_STATUS_FORMAT = "{\"eventType\": \"ComponentStatus\", "
            +" \"event\": {\"id\": \"{}\", \"label\": \"{}\", \"status\": \"{}\", \"value\": \"{}\"}}";

    private static final Logger LOGGER = LoggerFactory.getLogger(StatusPageGenerator.class);
    
    private final String applicationId;
    private final VersionComponent versionComponent;
    private final List<Component> components = new ArrayList<Component>();
    
    public StatusPageGenerator(String applicationId, VersionComponent versionComponent) {
        this.applicationId = applicationId;
        this.versionComponent = versionComponent;
        components.add(versionComponent);
    }
    
    public void addComponent(Component component) {
        components.add(component);
    }
    
    public StatusPage getApplicationReport() {
        Map<Component, Report> componentReports = new LinkedHashMap<Component, Report>(components.size());
        for (Component component : components) {
            Report report;
            try {
                report = component.getReport();
            } catch (Throwable e) {
                LOGGER.error("exception getting report from component {}", component.getId(), e);
                report = new Report(e);
            }

            if (Status.CRITICAL.equals(report.getStatus()) || Status.WARNING.equals(report.getStatus())) {
                LOGGER.info(COMPONENT_STATUS_FORMAT, component.getId(), component.getLabel(), report.getStatus(), report.getValue());
            }

            componentReports.put(component, report);
        }
        return new StatusPage(applicationId, componentReports);
    }

    public Component getVersionComponent() {
        return versionComponent;
    }
}

@@ -1275,16 +1275,29 @@
  public 
+synchronized 
 void add
@@ -1321,32 +1321,32 @@
 nt component) %7B%0A
-
         componen
@@ -1418,24 +1418,81 @@
 nReport() %7B%0A
+        List%3CComponent%3E snapshot = componentsSnapshot();%0A
         Map%3C
@@ -1566,26 +1566,24 @@
 Report%3E(
-components
+snapshot
 .size())
@@ -1619,26 +1619,24 @@
 onent : 
-components
+snapshot
 ) %7B%0A    
@@ -2386,11 +2386,135 @@
 t;%0A    %7D
+%0A%0A    private synchronized List%3CComponent%3E componentsSnapshot() %7B%0A        return new ArrayList%3CComponent%3E(components);%0A    %7D
 %0A%7D%0A

synchronize access to components list and iterate over a snapshot