/*
 * Copyright (c) 2004-2017, by Alex Leigh.
 * All rights reserved.
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE
 * The copyright notice above does not evidence any
 * actual or intended publication of such source code.
 */

package leigh.eo.schema.dao;

import leigh.eo.EO;
import leigh.eo.EODataType;
import leigh.eo.schema.DAOGenerator;
import leigh.mecha.log.MechaLogger;
import leigh.mecha.log.MechaLoggerFactory;
import leigh.mecha.util.UniversalJob;

import java.io.File;
import java.io.FileNotFoundException;

/**
 * This class generates the schema^2 (that is, the schema for the schema). In turn this schema can be used to generateJava
 * the DAO objects for the schema components (Element, Loop, Field, etc). These schema DAOs are used throughout
 * the ESP codebase.
 *
 * @author Alex Leigh
 */
public final class Apotheosis {
    private static final MechaLogger logger = MechaLoggerFactory.getLogger(Apotheosis.class);

    // Observe the procedures of a general alert

    public static EO generate() {
        final EO schema = SchemaUtil.create(SchemaUtil.API_KEY);

        final EO labelField = SchemaUtil.createLabelField();
        final EO apiNameField = FieldUtil.create("apiName", "API Name", EODataType.string);

        SchemaElementDAO.appendLabel(schema, TextUtil.defaultLabel("Record Schema"));

        // The Makers of the Makers fall before the child

        // Label
        final EO label = ElementElementDAO.create();
        SchemaElementDAO.getElements(schema).add(label);
        ElementElementDAO.setApiName(label, TextElementDAO.API_TYPE);
        ElementElementDAO.getFields(label).add(FieldUtil.create("locale", "Locale", EODataType.locale));
        ElementElementDAO.getFields(label).add(FieldUtil.create("text", "Text"));

        // Progress reports are arriving.

        // Element
        final EO element = ElementElementDAO.create();
        SchemaElementDAO.getElements(schema).add(element);
        ElementElementDAO.setApiName(element, ElementUtil.API_NAME);
        ElementElementDAO.getFields(element).add(apiNameField);
        ElementElementDAO.getFields(element).add(LoopUtil.create("fields", "Fields"));

        // Field
        final EO field = ElementElementDAO.create();
        SchemaElementDAO.getElements(schema).add(field);
        ElementElementDAO.setApiName(field, FieldUtil.API_NAME);
        ElementElementDAO.getFields(field).add(apiNameField);
        ElementElementDAO.getFields(field).add(labelField);
        ElementElementDAO.getFields(field).add(FieldUtil.create("type", "Type"));
        ElementElementDAO.getFields(field).add(FieldUtil.create("isCaseInsensitive", "Case Insensitive",
                EODataType.bool));
        // Hidden fields will not display in standard forms
        ElementElementDAO.getFields(field).add(FieldUtil.create("isHidden", "Hidden", EODataType.bool));
        ElementElementDAO.getFields(field).add(FieldUtil.create("isProtected", "Protected", EODataType.bool));
        ElementElementDAO.getFields(field).add(LoopUtil.create("fixedChoices", "Fixed Choices"));
        ElementElementDAO.getFields(field).add(LoopUtil.create("validators", "Validators"));
        ElementElementDAO.getFields(field).add(FieldUtil.create("help", "Help Text"));
        ElementElementDAO.getFields(field).add(FieldUtil.create("defaultValue", "Default Value"));

        // Loop
        final EO loop = ElementElementDAO.create();
        SchemaElementDAO.getElements(schema).add(loop);
        ElementElementDAO.setApiName(loop, LoopUtil.API_NAME);
        ElementElementDAO.getFields(loop).add(apiNameField);
        ElementElementDAO.getFields(loop).add(labelField);
        ElementElementDAO.getFields(loop).add(LoopUtil.create("acceptTypes", "Accept Types",
                new String[]{AcceptTypeElementDAO.API_TYPE}));

        // FixedChoice
        final EO acceptType = ElementElementDAO.create();
        SchemaElementDAO.getElements(schema).add(acceptType);
        ElementElementDAO.setApiName(acceptType, AcceptTypeElementDAO.API_TYPE);
        ElementElementDAO.getFields(acceptType).add(FieldUtil.createNotNull("elementApiName", "Element API Name"));

        // FixedChoice
        final EO fixedChoice = ElementElementDAO.create();
        SchemaElementDAO.getElements(schema).add(fixedChoice);
        ElementElementDAO.setApiName(fixedChoice, FixedChoiceElementDAO.API_TYPE);
        ElementElementDAO.getFields(fixedChoice).add(FieldUtil.create(FixedChoiceElementDAO.KEY_VALUE, "Value",
                EODataType.string));
        ElementElementDAO.getFields(fixedChoice).add(labelField);

        // Custom Proc
        final EO customProc = ElementElementDAO.create();
        SchemaElementDAO.getElements(schema).add(customProc);
        ElementElementDAO.setApiName(customProc, "Procedure");
        ElementElementDAO.getFields(customProc).add(apiNameField);
        ElementElementDAO.getFields(customProc).add(labelField);
        ElementElementDAO.getFields(customProc).add(FieldUtil.createNotNull("engine", "Script Engine"));
        ElementElementDAO.getFields(customProc).add(FieldUtil.createNotNull("script", "Code"));

        // Schema
        final EO schemaElement = ElementElementDAO.create();
        SchemaElementDAO.getElements(schema).add(schemaElement);
        ElementElementDAO.setApiName(schemaElement, SchemaUtil.API_KEY);
        ElementElementDAO.getFields(schemaElement).add(apiNameField);
        ElementElementDAO.getFields(schemaElement).add(labelField);
        ElementElementDAO.getFields(schemaElement).add(LoopUtil.create("elements", "Elements"));
        ElementElementDAO.getFields(schemaElement).add(LoopUtil.create("procedures", "Custom Procedures"));

        final EO notEmptyValidator = ElementElementDAO.create();
        SchemaElementDAO.getElements(schema).add(notEmptyValidator);
        ElementElementDAO.setApiName(notEmptyValidator, "leigh.esp.eo.schema.ValidatorNotEmpty");

        return schema;
    }

    public static void main(final String... args) throws FileNotFoundException {
        UniversalJob.banner(logger, "Apotheosis mk3", "2014 Alex Leigh");
        final EO schema = generate();
        final DAOGenerator gen = new DAOGenerator(new File("leigh-eo-schema/src/main/java"));
        gen.generateJava("org.leigh.eo.schema", schema);

        logger.info("Generated schema: {}", schema);
    }
}
