/*-
 * ~~~~~~licensing~~~~~~
 * application-impl
 * ==========
 * 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.impl.project.model;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

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

import ru.entaxy.platform.base.support.JSONUtils.JsonTraverse;
import ru.entaxy.platform.integration.applications.ApplicationProjectContent;
import ru.entaxy.platform.integration.applications.impl.project.ApplicationProjectContentImpl;
import ru.entaxy.platform.integration.applications.impl.project.ApplicationProjectItemImpl;
import ru.entaxy.platform.integration.applications.impl.project.model.item.BundleItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ConfigItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ContentModelItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ObjectItem;
import ru.entaxy.platform.integration.applications.impl.project.model.item.ResourceItem;
import ru.entaxy.platform.integration.applications.item.project.EntaxyBundleItem;
import ru.entaxy.platform.integration.applications.item.project.EntaxyConfigItem;
import ru.entaxy.platform.integration.applications.item.project.EntaxyObjectItem;
import ru.entaxy.platform.integration.applications.item.project.EntaxyResourceItem;

public class ContentModel {

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

    public static ContentModel load(JsonObject jsonObject) {
        ContentModel result = GSON.fromJson(jsonObject, ContentModel.class);
        JsonTraverse traverser = new JsonTraverse().checker(new ContentChecker(result));
        traverser.traverse(jsonObject);
        return result;
    }

    String application = "";
    String group = "";
    String version = "";
    String createdOn = Calendar.getInstance().getTimeInMillis() + "";
    String createdBy = "";
    String modifiedOn = "";
    String modifiedBy = "";

    transient List<ContentModelItem> requiredItems = new ArrayList<>();
    transient List<ContentModelItem> includedItems = new ArrayList<>();

    public void update(ApplicationProjectContentImpl applicationContentImpl) {

        application = applicationContentImpl.getProperties()
                .getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.APPLICATION, application).toString();
        group = applicationContentImpl.getProperties()
                .getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.GROUP, group).toString();
        version = applicationContentImpl.getProperties()
                .getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.VERSION, version).toString();
        createdOn = applicationContentImpl.getProperties()
                .getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.CREATED_ON, createdOn).toString();
        createdBy = applicationContentImpl.getProperties()
                .getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.CREATED_BY, createdBy).toString();
        modifiedOn = applicationContentImpl.getProperties()
                .getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.MODIFIED_ON, modifiedOn).toString();
        modifiedBy = applicationContentImpl.getProperties()
                .getOrDefault(ApplicationProjectContent.STANDARD_PROPERTIES.MODIFIED_BY, modifiedBy).toString();

        requiredItems.clear();
        includedItems.clear();
        for (ApplicationProjectItemImpl item : applicationContentImpl.getItemsMap().values()) {
            List<ContentModelItem> targetList;
            if (item.isRequired())
                targetList = requiredItems;
            else
                targetList = includedItems;
            ContentModelItem converted = convert(item);
            targetList.add(converted);
        }
    }

    public JsonObject getAsJson() {
        JsonElement je = GSON.toJsonTree(this, ContentModel.class);
        if (!je.isJsonObject()) {
            return new JsonObject();
        }
        JsonObject result = je.getAsJsonObject();

        // add requirements
        JsonArray ja = new JsonArray();
        for (ContentModelItem item : requiredItems) {
            JsonElement itemElement = GSON.toJsonTree(item, item.getClass());
            ja.add(itemElement);
        }
        result.add("requirements", ja);

        // add items
        ja = new JsonArray();
        for (ContentModelItem item : includedItems) {
            JsonElement itemElement = GSON.toJsonTree(item, item.getClass());
            ja.add(itemElement);
        }
        result.add("items", ja);

        return result;
    }

    protected ContentModelItem convert(ApplicationProjectItemImpl item) {
        ContentModelItem result = null;
        switch (item.getType()) {
            case BUNDLE:
                result = new BundleItem();
                break;
            case OBJECT:
                result = new ObjectItem();
                break;
            case CONFIG:
                result = new ConfigItem();
                break;
            case RESOURCE:
                result = new ResourceItem();
                break;
            default:
                return null;
        }
        result.setContentModel(this);
        result.setId(item.getId());
        result.setGhost(item.isGhost());
        result.setIgnored(item.isIgnored());
        result.setItemScope(item.getScope());
        result.setItemType(item.getType());
        result.setRequired(item.isRequired());

        if (item.getColocationGroup() != null)
            result.setColocationGroupId(item.getColocationGroup().getId());

        if (item instanceof EntaxyBundleItem) {
            BundleItem typedResult = (BundleItem) result;
            EntaxyBundleItem typedOrigin = (EntaxyBundleItem) item;
            typedResult.setBundleId(typedOrigin.getBundleId());
            typedResult.setBundleSymbolicName(typedOrigin.getBundleSymbolicName());
        }

        if (item instanceof EntaxyObjectItem) {
            ObjectItem typedResult = (ObjectItem) result;
            EntaxyObjectItem typedOrigin = (EntaxyObjectItem) item;
        }

        if (item instanceof EntaxyConfigItem) {
            ConfigItem typedResult = (ConfigItem) result;
            EntaxyConfigItem typedOrigin = (EntaxyConfigItem) item;
        }

        if (item instanceof EntaxyResourceItem) {
            ResourceItem typedResult = (ResourceItem) result;
            EntaxyResourceItem typedOrigin = (EntaxyResourceItem) item;
        }

        return result;
    }

    public String getApplication() {
        return application;
    }

    public void setApplication(String application) {
        this.application = application;
    }

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getCreatedOn() {
        return createdOn;
    }

    public void setCreatedOn(String createdOn) {
        this.createdOn = createdOn;
    }

    public String getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    public String getModifiedOn() {
        return modifiedOn;
    }

    public void setModifiedOn(String modifiedOn) {
        this.modifiedOn = modifiedOn;
    }

    public String getModifiedBy() {
        return modifiedBy;
    }

    public void setModifiedBy(String modifiedBy) {
        this.modifiedBy = modifiedBy;
    }

    public List<ContentModelItem> getRequiredItems() {
        return requiredItems;
    }

    public List<ContentModelItem> getIncludedItems() {
        return includedItems;
    }

}
