package com.socrata.datasync.config.controlfile;

import com.socrata.datasync.PublishMethod;
import com.socrata.datasync.Utils;
import com.socrata.datasync.job.IntegrationJob;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.util.TreeMap;

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown=true)
@JsonPropertyOrder(alphabetic=true)
public class ControlFile {

    public String action;
    public String opaque;

    public FileTypeControl csv;
    public FileTypeControl tsv;
    public Boolean replacePreviousQueued;

    // NB: when using a mapper to read this class, you must enable
    // DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY, if either of the timestamp formats
    // in csvControl or tsvControl are strings, rather than arrays of strings.
    public ControlFile() {}

    public ControlFile(String action, String opaque, FileTypeControl csvControl, FileTypeControl tsvControl, Boolean replacePreviousQueued) {
        this.action = action;
        this.opaque = opaque;
        this.csv = csvControl;
        this.tsv = tsvControl;
        this.replacePreviousQueued = replacePreviousQueued;
    }


    // Hack city.  Apparently the ControlFile must have both a csv and a tsv control file, even though only one may be
    // active at any given time.  The control file editor will be manipulating the active one, regardless of type.
    // Thus, I need to return the active FTC here that can later be manipulated throughout the model.
    @JsonIgnore
    public FileTypeControl getFileTypeControl(){
        if (csv != null)
            return csv;
        else
            return tsv;
    }

    @JsonIgnore
    public FileTypeControl getCsvFtc(){
        return csv;
    }

    @JsonIgnore
    public FileTypeControl getTsvFtc(){
        return tsv;
    }


    /**
    * Generates the default ControlFile object based on given job parameters
    *
    * @param fileToPublish filename of file to publish (.tsv or .csv file)
    * @param publishMethod to use to publish (upsert, append, replace, or delete)
    *               NOTE: this option will be overriden if this control file is for an ftp job
    * @param columns the column headers corresponding to the filetoPublish, needed if it lacks headers
    * @param useSocrataGeocoding if true use Socrata's geocoding to geocode Location columns
    * @return content of control.json based on given job parameters
    */
    public static ControlFile generateControlFile(final String fileToPublish,
                                                  final PublishMethod publishMethod,
                                                  final String[] columns,
                                                  final boolean useSocrataGeocoding,
                                                  final boolean hasHeaderRow) {


        String fileToPublishExtension = Utils.getFileExtension(fileToPublish);


        boolean isCsv = fileToPublishExtension.equalsIgnoreCase("csv");
        String quote = isCsv ? "\"" : "\u0000";

        FileTypeControl ftc = new FileTypeControl()
                .columns(columns)
                .encoding("utf-8")
                .hasHeaderRow(hasHeaderRow)
                .quote(quote);

        int skip = 0;
        String separator = isCsv ? "," : "\t";
        //Adding our standard export formats so that a customer can easily round-trip data into the system.
        String[] timeFormats = new String[]{"ISO8601", "MM/dd/yy", "MM/dd/yyyy", "dd-MMM-yyyy","MM/dd/yyyy hh:mm:ss a Z","MM/dd/yyyy hh:mm:ss a"};
        ftc.emptyTextIsNull(true)
           .filePath(fileToPublish)
           .ignoreColumns(new String[]{})
           .fixedTimestampFormat(timeFormats)
           .floatingTimestampFormat(timeFormats)
           .separator(separator)
           .skip(skip)
           .timezone("UTC")
           .useSocrataGeocoding(useSocrataGeocoding)
           .trimWhitespace(true)
           .trimServerWhitespace(false)
           .overrides(new TreeMap<String, ColumnOverride>())
           .setAsideErrors(false);


        // for replace jobs, calculate column statistics
        if (PublishMethod.replace.equals(publishMethod))
            ftc.columnStatistics(true);

        if (isCsv) {
            return new ControlFile(Utils.capitalizeFirstLetter(publishMethod.name()), null, ftc, null, null);
        } else {
            return new ControlFile(Utils.capitalizeFirstLetter(publishMethod.name()), null, null, ftc, null);
        }
    }

    public String generateAndAddOpaqueUUID() {
        String uuid = Utils.generateRequestId();
        this.opaque = uuid;
        return uuid;
    }
}


@@ -3765,16 +3765,29 @@
 mm:ss a%22
+,%22yyyy-MM-dd%22
 %7D;%0A     

Add date format by request