package com.capgemini.framework.teamcenter.files;

import com.capgemini.framework.teamcenter.ServiceDataHelper;
import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.exceptions.ConnectionMisconguredException;
import com.capgemini.framework.teamcenter.exceptions.MalformedDataSetException;
import com.teamcenter.services.loose.core._2006_03.FileManagement.GetDatasetWriteTicketsInputData;
import com.teamcenter.soa.client.model.ServiceData;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * Use this class to transfer files into datasets.
 */
@Getter(value = AccessLevel.PROTECTED)
public class FileManagement {

    private final TcSession session;
    private final List<GetDatasetWriteTicketsInputData> dataSets = new ArrayList<>();

    public FileManagement(final TcSession session) {
        this.session = session;
    }

    /**
     * Creates a Dataset with a single file in it.
     *
     * @param session            a logged-in {@link TcSession}
     * @param datasetName        the name of the dataset
     * @param dataSetDescription a description for the dataset (optional: null or empty allowed))
     * @param file               a valid {@link File} pointing to the file on local file system to upload on the Tc servers
     * @param type               the {@link FileType} of file
     * @return a {@link GetDatasetWriteTicketsInputData} containing data on the dataset that has been created.
     * @throws MalformedDataSetException if anything goes wrong: missing file, conflicting names, wrong types etc.
     */
    public static GetDatasetWriteTicketsInputData addSingleDataSet(final TcSession session, final String datasetName,
                                                                   final String dataSetDescription, final File file, final FileType type) throws MalformedDataSetException, ConnectionMisconguredException {
        FileManagement fileManagement;
        fileManagement = new FileManagement(session);
        fileManagement.addDataSetWithSingleFile(datasetName, dataSetDescription, file, type);
        fileManagement.upload();
        return fileManagement.dataSets.get(0); // Only one element
    }

    /**
     * Adds a dataset definition to the list of datasets to create, with a single file in it.
     *
     * @param datasetName        the name of the dataset
     * @param dataSetDescription a description for the dataset (optional: null or empty allowed))
     * @param file               a valid {@link File} pointing to the file on local file system to upload on the Tc servers
     * @param type               the {@link FileType} of file
     * @throws MalformedDataSetException if anything goes wrong: missing file, conflicting names, wrong types etc.
     */
    public void addDataSetWithSingleFile(final String datasetName, final String dataSetDescription, final File file, final FileType type)
            throws MalformedDataSetException {
        DatasetPreparator dataset = new DatasetPreparator(session, datasetName, dataSetDescription);
        dataset.addFile(file, type);
        addDataSet(dataset);
    }

    /**
     * Adds a custom {@link DatasetPreparator} instance to the batch of datasets to be uploaded.<br>
     */
    public void addDataSet(final DatasetPreparator dataset) throws MalformedDataSetException {
        if (!dataset.isCreated()) {
            dataset.prepare();
        }
        dataSets.add(dataset.getCreatedDataset());
    }

    /**
     * Uploads the files to each registered dataset in Tc.
     *
     * @throws MalformedDataSetException if anything goes wrong (the files were not uploaded
     */
    public void upload() throws MalformedDataSetException, ConnectionMisconguredException {
        if (dataSets.isEmpty()) {
            throw new MalformedDataSetException("No dataset was provided, unable to create the datasets.");
        }
        GetDatasetWriteTicketsInputData[] datasetTickets = dataSets.toArray(new GetDatasetWriteTicketsInputData[dataSets.size()]);
        ServiceData response = session.getFileManagementUtility().putFiles(datasetTickets);
        if (ServiceDataHelper.hasErrors(response)) {
            ServiceDataHelper.displayErrors(response);
            throw new MalformedDataSetException("Unable to perform fully the request, file upload may have failed");
        }
    }

    /**
     * Enums of each file type supported as a Teamcenter dataset file.
     */
    @Getter
    @AllArgsConstructor
    public enum FileType {
        /**
         * Generic Text document.
         */
        TEXT_FILE("Text", "Text", true),
        /**
         * 'Fiche Article' PDF document on Parts.
         */
        FICHE_ARTICLE("Fiche Article", "PDF_Reference", false),
        /**
         * Generic PDF document.
         */
        PDF("PDF", "PDF_Reference", false);

        private final String type;
        private final String namedReferenceName;
        private final boolean text;
    }

}
