/*-
 * ~~~~~~licensing~~~~~~
 * data-mapper-runtime
 * ==========
 * Copyright (C) 2020 - 2025 EmDev LLC
 * ==========
 * You may not use this file except in accordance with the License Terms of the Copyright
 * Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
 * rights to the Software and any copies are the property of the Copyright Holder. Unless
 * it is explicitly allowed the Copyright Holder, the User is prohibited from using the
 * Software for commercial purposes to provide services to third parties.
 * 
 * The Copyright Holder hereby declares that the Software is provided on an "AS IS".
 * Under no circumstances does the Copyright Holder guarantee or promise that the
 * Software provided by him will be suitable or not suitable for the specific purposes
 * of the User, that the Software will meet all commercial and personal subjective
 * expectations of the User, that the Software will work properly, without technical
 * errors, quickly and uninterruptedly.
 * 
 * Under no circumstances shall the Copyright Holder or its Affiliates is not liable
 * to the User for any direct or indirect losses of the User, his expenses or actual
 * damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
 * or damage to data, property, etc.
 * ~~~~~~/licensing~~~~~~
 */
package ru.entaxy.platform.modules.datamapper;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.modules.datamapper.exceptions.DataMapperException;
import ru.entaxy.platform.modules.datamapper.exceptions.DataMapperNotFoundException;

public interface DataMapperService {

    String DEFAULT_MAPPER_ID = "entaxy-default";

    List<DataMapper> getDataMappers();

    DataMapper getDataMapper(String id);

    default List<String> getDataMapperIds() {
        return getDataMappers().stream().map(dm -> dm.getId()).collect(Collectors.toList());
    }

    default List<String> getMaps(String mapperId) {
        DataMapper mapper = getDataMapper(mapperId);
        if (mapper == null)
            return Collections.emptyList();
        return mapper.getMaps();
    };

    default Object getValue(String mapSignature, Object sourceValue, boolean isTrimForString) {
        try {
            return getValueUnsafe(mapSignature, sourceValue, isTrimForString);
        } catch (Exception e) {
            return null;
        }
    }

    default Object getValueUnsafe(String mapSignature, Object sourceValue, boolean isTrimForString) throws DataMapperException {
        String mapName = DataMapper.DEFAULT_MAP;
        String mapperId = DataMapperService.DEFAULT_MAPPER_ID;
        if (CommonUtils.isValid(mapSignature)) {
            String[] splitted = mapSignature.split("@");
            if (splitted.length > 0) {
                String mapperIdVal = CommonUtils.getValid(splitted[splitted.length - 1], "");
                if (CommonUtils.isValid(mapperIdVal))
                    mapperId = mapperIdVal;
                if (splitted.length > 1) {
                    String mapNameVal = CommonUtils.getValid(splitted[0], "");
                    if (CommonUtils.isValid(mapNameVal))
                        mapName = mapNameVal;
                }
            }
        }
        return getValueUnsafe(mapperId, mapName, sourceValue,isTrimForString);
    }

    default Object getValue(String dataMapperId, String mapName, Object sourceValue, boolean isTrimForString) {
        try {
            return getValueUnsafe(dataMapperId, mapName, sourceValue, isTrimForString);
        } catch (Exception e) {
            return null;
        }
    }

    default Object getValueUnsafe(String dataMapperId, String mapName, Object sourceValue, boolean isTrimForString)
            throws DataMapperException {
        DataMapper dataMapper = getDataMapper(dataMapperId);
        if (dataMapper == null)
            throw new DataMapperNotFoundException(dataMapperId);
        return dataMapper.getMapValue(mapName, sourceValue, isTrimForString);
    }

    default List<String> getMapSignatures() {
        List<String> result = new ArrayList<>();
        for (DataMapper dm : getDataMappers())
            result.addAll(
                    dm.getMaps().stream().map(m -> String.format("%s@%s", m, dm.getId())).collect(Collectors.toList()));
        return result;
    }

    default List<String> getMapSignaturesSorted() {
        List<String> result = getMapSignatures();
        Collections.sort(result, new Comparator<String>() {

            @Override
            public int compare(String o1, String o2) {
                String[] o1splitted = o1.split("@");
                String[] o2splitted = o2.split("@");
                int result = o1splitted[1].compareTo(o2splitted[1]);
                if (result != 0)
                    return result;
                return o1splitted[0].compareTo(o2splitted[0]);
            }
        });
        return result;
    }
}
