library("TSP")

sysname <- Sys.info()["sysname"]

if (sysname == "Linux") {
  concorde_path(file.path(getwd(), "../../bin/linux"))
} else if (sysname == "Darwin") {
  concorde_path(file.path(getwd(), "../../bin/osx"))
} else {
  stop("Unknown platform " + sysname + ".")
}

copy_concorde_to_scratch = function() {
  to <- file.path("/scratch", Sys.getenv("USER"))
  if (!file.exists(to))
    dir.create(to) 
  file.copy(file.path(concorde_path(), "concorde"), to)
  concorde_path(to)
}

concorde <- function(x, control=NULL) {
  clo <- if (!is.null(control$clo)) 
    control$clo
  else ""
  precision <- if (!is.null(control$precision)) 
    control$precision
  else 6
  exe <- TSP:::.find_exe(control$exe, "concorde")
  if (!inherits(x, "TSP")) 
    stop("Concorde only solves symmetric TSPs.")
  shift <- 0
  x_pos_inf <- x == Inf
  x_neg_inf <- x == -Inf
  x[x_pos_inf] <- NA
  x[x_neg_inf] <- NA
  max_x <- max(x, na.rm = TRUE)
  if (any(x_pos_inf) || any(x_neg_inf)) {
    min_x <- min(x, na.rm = TRUE)
    inf_val <- 2 * max(abs(c(max_x, min_x)))
    if (min_x < 0) 
      shift <- -min_x
    if (any(x_neg_inf)) {
      cat("Neg. infinity values are replaced by", 0,
          "and all\n                distances are increased by", 
          inf_val, "\n")
      x <- x + inf_val
      x[x_neg_inf] <- 0
      shift <- inf_val
    }
    if (any(x_pos_inf)) {
      cat("Pos. infinity values are replaced by", inf_val + 
          shift, "\n")
      x[x_pos_inf] <- inf_val + shift
    }
  }
  max_x <- max(x)
  if (n_of_cities(x) < 10) {
    MAX <- 2^15
    if (max_x > MAX) 
      stop("Concorde can only handle distances < 2^15 for less than 10 cities")
    prec <- floor(log10(MAX/max_x))
    if (prec < precision) {
      precision <- prec
      warning(paste("Concorde can only handle distances < 2^15 for", 
                    "less than 10 cities. Reducing precision to", 
                    precision), immediate. = TRUE)
    }
  }
  else {
    MAX <- 2^31 - 1
    prec <- floor(log10(MAX/max_x/n_of_cities(x)))
    if (prec < precision) {
      precision <- prec
      warning(paste("Reducing precision for Concorde to", 
                    precision), immediate. = TRUE)
    }
  }
  wd <- tempdir()
  temp_file <- tempfile(tmpdir = wd)
  tmp_file_in <- paste(temp_file, ".dat", sep = "")
  tmp_file_out <- paste(temp_file, ".sol", sep = "")
  write_TSPLIB(x, file = tmp_file_in, precision = precision)
  dir <- getwd()
  setwd(wd)
  on.exit(setwd(dir))
  system(paste(exe, "-x", "-o", tmp_file_out, clo, tmp_file_in),
         ignore.stdout=TRUE, ignore.stderr=TRUE)
  if (!file.access(tmp_file_out) == 0) 
    stop("Problems with reading Concorde's output.
Is concorde properly installed?")
  order <- scan(tmp_file_out, what = integer(0), quiet = TRUE)
  order <- order[-1] + as.integer(1)
  unlink(c(tmp_file_in, tmp_file_out))
  order
}
