package com.technia.tif.enovia.job.executors.file.java;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;

import com.technia.common.poi.property.Property;
import com.technia.common.poi.property.PropertyHandler;
import com.technia.common.poi.property.PropertyHandlers;
import com.technia.common.poi.property.Type;
import com.technia.tif.core.TIFRuntimeException;
import com.technia.tif.core.annotation.CopyToDocumentation;
import com.technia.tif.core.startup.TIFServer;
import com.technia.tif.enovia.job.executors.file.FileActionContext;
import com.technia.tif.enovia.job.executors.file.FileActionResult;
import com.technia.tif.enovia.job.executors.file.SetProperties;
import com.technia.tif.enovia.job.executors.file.StatusLog;

/**
 * Updates properties of Office document using POI library.
 *
 * @since 2018.3.0
 */
public class POIPropertyUpdater extends SetProperties {

    @Override
    protected FileActionResult process(FileActionContext ctx) throws Exception {
        perform(ctx.getLog(), ctx.getFile(), resolveProperties(ctx.getObjectId(), ctx.getFormat(), ctx.getFileName()));
        return new FileActionResult(ctx.getFile());
    }

    /**
     * Main entry point of the class.
     *
     * @param input Input file
     * @param setProperties SetProperties action
     */
    public void perform(StatusLog log, File input, Map<String, Object> properties) throws IOException {
        PropertyHandlers handlers = TIFServer.getInstance().getTIFConfig().getFeature(PropertyHandlers.class);
        if (handlers == null) {
            throw new TIFRuntimeException(
                    "There is no property handler support installed. Please verify extension 'docprops'");
        }

        PropertyHandler handler = handlers.resolve(input.toPath());
        if (handler != null) {
            Property[] props = properties.entrySet()
                .stream()
                .map(this::toProperty)
                .collect(Collectors.toList())
                .toArray(new Property[properties.size()]);
            log.log("About to update %d properties of file %s", props.length, input.getName());
            handler.setProperties(input.toPath(), props);
        } else {
            log.log("The POI property handler doesnt support the file: %s. Skipping...", input.getAbsolutePath());
        }
    }

    private Property toProperty(Map.Entry<String, Object> entry) {
        if (entry.getValue() instanceof Date) {
            return new Property(entry.getKey(), entry.getValue(), Type.DATETIME);
        } else if (entry.getValue() instanceof Integer) {
            return new Property(entry.getKey(), entry.getValue(), Type.INT);
        } else if (entry.getValue() instanceof Boolean) {
            return new Property(entry.getKey(), entry.getValue(), Type.BOOL);
        } else if (entry.getValue() instanceof Double) {
            return new Property(entry.getKey(), entry.getValue(), Type.REAL);
        } else if (entry.getValue() instanceof Float) {
            return new Property(entry.getKey(), entry.getValue(), Type.REAL);
        } else if (entry.getValue() != null) {
            return new Property(entry.getKey(), entry.getValue().toString(), Type.STRING);
        } else {
            return new Property(entry.getKey(), "", Type.UNKNOWN);
        }
    }

}
