package ru.yandex.autodoc.common.doc.result;

import ru.yandex.autodoc.common.doc.types.AnyObjectModel;
import ru.yandex.autodoc.common.doc.types.ObjectModel;
import ru.yandex.autodoc.common.out.json.JsonValueWriter;
import ru.yandex.autodoc.common.out.json.builder.ContainerBuilder;
import ru.yandex.autodoc.common.out.json.builder.JsonValueBuilder;
import ru.yandex.autodoc.common.util.enums.EnumResolvers;
import ru.yandex.autodoc.common.util.enums.IEnumResolver;

/**
 * @author avhaliullin
 */
public abstract class MethodResult {
    public static final MethodResult NO_RESULT = new SimpleResult(Type.NONE, "");

    protected final Type type;

    protected MethodResult(Type type) {
        this.type = type;
    }

    public Type getType() {
        return type;
    }

//    public abstract String getResultDescription();

    public static abstract class ObjectResult extends MethodResult {
        private final AnyObjectModel model;

        public ObjectResult(AnyObjectModel model) {
            super(Type.OBJECT);
            this.model = model;
        }

        public AnyObjectModel getModel() {
            return model;
        }
    }

    public static abstract class DocumentedJsonResult extends MethodResult implements JsonValueWriter {
        public DocumentedJsonResult() {
            super(Type.JSON);
        }
    }

    private static class CustomResult extends SimpleResult {

        private CustomResult(String description) {
            super(Type.CUSTOM, description);
        }
    }

    private static class SimpleResult extends MethodResult {
        private final String description;

        private SimpleResult(Type tpe, String result) {
            super(Type.CUSTOM);
            this.description = result;
        }

        public String getResultDescription() {
            return description;
        }
    }

    public static DocumentedJsonResult createJsonValueResult(final JsonValueWriter writer) {
        return new DocumentedJsonResult() {
            @Override
            public <C extends ContainerBuilder> C writeValue(JsonValueBuilder<C> builder) {
                return writer.writeValue(builder);
            }
        };
    }

    public static MethodResult createCustom(String description) {
        return new CustomResult(description);
    }

    public static enum Type {
        JSON,
        CUSTOM,
        NONE,
        OBJECT,
        ;

        public static final IEnumResolver<Type> R = EnumResolvers.r(Type.class);
    }
}
