/*-
 * ~~~~~~licensing~~~~~~
 * resource-based-storage
 * ==========
 * 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.integration.applications.storage.resource.impl;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;

import ru.entaxy.esb.resources.EntaxyResource;
import ru.entaxy.esb.resources.EntaxyResourceMetadata;
import ru.entaxy.platform.base.support.JSONUtils;

public abstract class AbstractResourceComponent<T> {

    private static final Logger log = LoggerFactory.getLogger(AbstractResourceComponent.class);

    protected static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();

    protected ResourceContext resourceContext;

    // protected EntaxyResourceService entaxyResourceService;

    // protected EntaxyResource rootResourceFolder;
    protected EntaxyResourceMetadata rootResourceFolderMetadata;

    protected EntaxyResource rootResource;

    // protected String rootResourceFolderUrl;
    protected String rootResourceUrl;

    protected boolean isInited = false;

    protected T dataObject;

    protected abstract Class<T> getDataObjectClass();

    protected abstract String getRootResourceName();

    protected abstract T createDataObject();

    /*
    protected AbstractResourceComponent(EntaxyResourceService entaxyResourceService) {
        super();
        setEntaxyResourceService(entaxyResourceService);
    }
    */

    protected AbstractResourceComponent(ResourceContext resourceContext) {
        super();
        this.resourceContext = resourceContext;
        this.resourceContext.init();
    }


    protected T loadDataObject(JsonObject jsonObject) {
        return GSON.fromJson(jsonObject, getDataObjectClass());
    };

    protected void initializeRootResource() throws Exception {
        dataObject = createDataObject();
        updateRootResource();
    }

    protected void initializeDataObject() throws Exception {
        try (InputStream is = rootResource.getInputStream()) {
            String data = new String(is.readAllBytes());
            dataObject = GSON.fromJson(JSONUtils.getJsonRootObject(data), getDataObjectClass());
        }
    }

    protected void updateRootResource() throws Exception {
        JsonObject jsonObject = GSON.toJsonTree(dataObject).getAsJsonObject();
        String data = GSON.toJson(jsonObject);
        try (ByteArrayInputStream bis = new ByteArrayInputStream(data.getBytes())) {
            rootResource.save(bis);
        } catch (Exception e) {
            throw e;
        }
    }

    protected EntaxyResource getResource(String relPath) {
        /*
        String targetUrl = rootResourceFolderUrl;
        if (rootResourceFolderUrl.charAt(rootResourceFolderUrl.length() - 1) != '/')
            targetUrl = targetUrl.concat("/");
        if (relPath.charAt(0) == '/')
            targetUrl = targetUrl.concat(relPath.substring(1));
        else
            targetUrl = targetUrl.concat(relPath);
        EntaxyResource result = entaxyResourceService.getResource(targetUrl);
        return result;
        */
        return resourceContext.getResource(relPath);
    }

    public void init() {

        // rootResourceFolder = entaxyResourceService.getResource(rootResourceFolderUrl);

        // rootResource = entaxyResourceService
        // .getResource(rootResourceFolder.getURL().concat("/").concat(getRootResourceName()));
        rootResource = resourceContext.getResource(getRootResourceName());
        if (!rootResource.exists()) {
            try {
                initializeRootResource();
            } catch (Exception ignore) {

            }
        } else {
            try {
                initializeDataObject();
            } catch (Exception e) {
                log.error("Error reading data from [" + rootResource.getURL() + "]", e);
                return;
            }
        }

        rootResourceFolderMetadata = resourceContext.getRootResourceFolder().getMetadata(true);

        isInited = true;

    }

    public ResourceContext getResourceContext() {
        return resourceContext;
    }

    public void save() {

    }

    public void delete() {
        if (!isInited)
            return;
        resourceContext.getRootResourceFolder().delete();
    }

    /*
    public void setEntaxyResourceService(EntaxyResourceService entaxyResourceService) {
        this.entaxyResourceService = entaxyResourceService;
    }
    */

    public String getRootResourceFolderUrl() {
        return resourceContext.getRootResourceFolderUrl();
    }

    /*
    public void setRootResourceFolderUrl(String rootResourceFolderUrl) {
        this.rootResourceFolderUrl = rootResourceFolderUrl;
    }
    */

    public abstract String getComponentKey();

}
