package org.batfish.job;

import java.nio.file.Path;
import java.util.Map;
import org.batfish.common.BatfishException;
import org.batfish.common.BatfishLogger;
import org.batfish.common.BatfishLogger.BatfishLoggerHistory;
import org.batfish.common.ParseTreeSentences;
import org.batfish.common.Warnings;
import org.batfish.datamodel.answers.ParseStatus;
import org.batfish.datamodel.answers.ParseVendorConfigurationAnswerElement;
import org.batfish.vendor.VendorConfiguration;

public class ParseVendorConfigurationResult
    extends BatfishJobResult<
        Map<String, VendorConfiguration>, ParseVendorConfigurationAnswerElement> {

  private final Path _file;

  private ParseTreeSentences _parseTree;

  private final ParseStatus _status;

  private VendorConfiguration _vc;

  private Warnings _warnings;

  public ParseVendorConfigurationResult(
      long elapsedTime, BatfishLoggerHistory history, Path file, Throwable failureCause) {
    super(elapsedTime, history, failureCause);
    _file = file;
    _status = ParseStatus.FAILED;
  }

  public ParseVendorConfigurationResult(
      long elapsedTime,
      BatfishLoggerHistory history,
      Path file,
      VendorConfiguration vc,
      Warnings warnings,
      ParseTreeSentences parseTree) {
    super(elapsedTime, history);
    _file = file;
    _parseTree = parseTree;
    _vc = vc;
    _warnings = warnings;
    // parse status is determined from other fields
    _status = null;
  }

  public ParseVendorConfigurationResult(
      long elapsedTime,
      BatfishLoggerHistory history,
      Path file,
      Warnings warnings,
      ParseStatus status) {
    super(elapsedTime, history);
    _file = file;
    _status = status;
    _warnings = warnings;
  }

  @Override
  public void appendHistory(BatfishLogger logger) {
    String terseLogLevelPrefix;
    if (logger.isActive(BatfishLogger.LEVEL_INFO)) {
      terseLogLevelPrefix = "";
    } else if (_vc != null) {
      terseLogLevelPrefix = _vc.getHostname() + ": ";
    } else {
      terseLogLevelPrefix = _file + ": ";
    }
    logger.append(_history, terseLogLevelPrefix);
  }

  @Override
  public void applyTo(
      Map<String, VendorConfiguration> vendorConfigurations,
      BatfishLogger logger,
      ParseVendorConfigurationAnswerElement answerElement) {
    appendHistory(logger);
    if (_vc != null) {
      String hostname = _vc.getHostname();
      if (vendorConfigurations.containsKey(hostname)) {
        throw new BatfishException("Duplicate hostname: " + hostname);
      } else {
        vendorConfigurations.put(hostname, _vc);
        if (!_warnings.isEmpty()) {
          answerElement.getWarnings().put(hostname, _warnings);
        }
        if (!_parseTree.isEmpty()) {
          answerElement.getParseTrees().put(hostname, _parseTree);
        }
        if (_vc.getUnrecognized()) {
          answerElement.getParseStatus().put(hostname, ParseStatus.PARTIALLY_UNRECOGNIZED);
        } else {
          answerElement.getParseStatus().put(hostname, ParseStatus.PASSED);
          answerElement.getFileMap().put(hostname, _file.getFileName().toString());
        }
      }
    } else {
      String filename = _file.getFileName().toString();
      answerElement.getParseStatus().put(filename, _status);
      if (_status == ParseStatus.FAILED) {
        answerElement
            .getErrors()
            .put(filename, ((BatfishException) _failureCause).getBatfishStackTrace());
      }
    }
  }

  public Path getFile() {
    return _file;
  }

  @Override
  public BatfishLoggerHistory getHistory() {
    return _history;
  }

  public VendorConfiguration getVendorConfiguration() {
    return _vc;
  }

  @Override
  public String toString() {
    if (_vc == null) {
      return "<EMPTY OR UNSUPPORTED FORMAT>";
    } else if (_vc.getHostname() == null) {
      return "<File: \"" + _file + "\" has indeterminate hostname>";
    } else {
      return "<" + _vc.getHostname() + ">";
    }
  }
}

@@ -2450,59 +2450,312 @@
     
-throw new BatfishException(%22Duplicate hostname: %22 +
+int index = 1;%0A        do %7B%0A          hostname = _vc.getHostname() + %22.dupname%22 + index;%0A          index++;%0A        %7D while (vendorConfigurations.containsKey(hostname));%0A        _warnings.redFlag(%0A            String.format(%0A                %22Found duplicate hostname %25s. Changed to %25s%22, _vc.getHostname(),
  hos
@@ -2760,24 +2760,25 @@
 ostname)
+)
 ;%0A      
 %7D else %7B
@@ -2765,35 +2765,61 @@
 me));%0A      
-%7D else %7B%0A  
+  _vc.setHostname(hostname);%0A      %7D%0A
       vendor
@@ -2855,26 +2855,24 @@
 _vc);%0A      
-  
 if (!_warnin
@@ -2879,34 +2879,32 @@
 gs.isEmpty()) %7B%0A
-  
         answerEl
@@ -2947,38 +2947,34 @@
 arnings);%0A      
- 
- 
 %7D%0A
-  
       if (!_pars
@@ -2988,26 +2988,24 @@
 sEmpty()) %7B%0A
-  
         answ
@@ -3059,30 +3059,26 @@
 ree);%0A      
-  %7D%0A  
+%7D%0A
       if (_v
@@ -3096,26 +3096,24 @@
 gnized()) %7B%0A
-  
         answ
@@ -3196,18 +3196,16 @@
 ;%0A      
-  
 %7D else %7B
@@ -3201,26 +3201,24 @@
    %7D else %7B%0A
-  
         answ
@@ -3283,26 +3283,24 @@
 D);%0A        
- 
- 
 answerElemen
@@ -3371,19 +3371,10 @@
     
-  %7D%0A      
 %7D
+%0A
 %0A   

allow duplicate router hostnames (#1128)