package com.workfusion.odf.impl.converter.extractor;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;

public abstract class AbstractRecursiveExtractor {
    protected Logger logger;

    /**
     * Constructor.
     *
     * @param logger
     */
    public AbstractRecursiveExtractor(final Logger logger) {
    	this.logger = logger;
    }

	public abstract String[] getExtensions();

    protected abstract List<DataWrapper> extract(DataWrapper dataWrapper);

    public List<DataWrapper> recursiveExtract(final byte[] data, final String name) {
        return recursiveExtract(new DataWrapper(data, name, null, null)); // Root DataWrapper
    }

    public List<DataWrapper> recursiveExtract(final DataWrapper dataWrapper) {
        ArrayList<String> parentsNames = new ArrayList<>();

        if (StringUtils.isNotBlank(dataWrapper.getName())) {
            parentsNames.add(dataWrapper.getName());
        }

        return recursiveExtract(dataWrapper, parentsNames);
    }

    private List<DataWrapper> recursiveExtract(final DataWrapper dataWrapper, final List<String> parentsNames) {
        List<DataWrapper> result = new ArrayList<>();

        List<DataWrapper> extractedDataWrappers = extract(dataWrapper);
        for (DataWrapper extractedDataWrapper : extractedDataWrappers) {
        	String name = extractedDataWrapper.getName();
            if (isContainer(name)) {
                List<String> newParentsNames = new ArrayList<>(parentsNames);
                newParentsNames.add(name);
                result.addAll(recursiveExtract(new DataWrapper(extractedDataWrapper.getData(), name, extractedDataWrapper.getType(), extractedDataWrapper.getAttributes()),
                		newParentsNames));
            } else {
                result.add(new DataWrapper(extractedDataWrapper.getData(), getEntryFullName(parentsNames, name), extractedDataWrapper.getType(), extractedDataWrapper.getAttributes()));
            }
        }

        return result;
    }

    private String getEntryFullName(final List<String> parentsNames, final String entryName) {
        final String parents = String.join("_", parentsNames);
        final String delemiterAfterParents = parents.isEmpty() ? "" : "_";
        return parents + delemiterAfterParents + entryName;
    }

    protected boolean isContainer(final String extention) {
        return Stream.of(getExtensions()).anyMatch(ext -> extention.toLowerCase().endsWith("." + ext.toLowerCase()));
    }
}
