import ps= require("./actualParse")
import ts = require("../src/typesystem")
import chai = require("chai");
const assert = chai.assert;
import nm=require("../src/nominals")
describe("To nominals",function() {
    it("built in types exist", function () {
        var tp = ps.parseJSON("Person", {
            type: "object",
            properties:{
                name: "string"
            }
        })
        var nt=nm.toNominal(tp,x=>null);
        assert.isNotNull(nt);
        assert.equal(nt.properties().length,1);
        assert(nt.properties()[0].range().nameId()=="string");
    });
    it("built in types exist", function () {
        var tp = ps.parseJSON("Person", {
            type: "object",
            properties:{
                name: "string"
            },
            facets:{
                "a": "number"
            }
        })
        var nt=nm.toNominal(tp,x=>null);
        assert.isNotNull(nt);
        assert(nt.allFacets()[0].range().nameId()=="number");
    });
    it("built in types exist", function () {
        var tp = ps.parseJSON("Person", {
            type: "object",
            properties:{
                name: "string"
            },
            facets:{
                "a": "number"
            }
        })
        var nt=nm.toNominal(tp,x=>null);
        assert.isNotNull(nt);
        assert(nt.allFacets()[0].range().nameId()=="number");
    });
    it("prop not optional", function () {
        var tp = ps.parseJSON("Person", {
            type: "object",
            properties:{
                name: "string"
            }
        })
        var nt=nm.toNominal(tp,x=>null);
        assert.isNotNull(nt);
        assert.equal(nt.properties().length,1);
        assert.isTrue(nt.properties()[0].isRequired());
    });
    it("prop optional", function () {
        var tp = ps.parseJSON("Person", {
            type: "object",
            properties:{
                "name?": "string"
            }
        })
        var nt=nm.toNominal(tp,x=>null);
        assert.isNotNull(nt);
        assert.equal(nt.properties().length,1);
        assert.isTrue(!nt.properties()[0].isRequired());
    });
    it("object hiearchy", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: "object",
                B: "A"

            }
        },ts.builtInRegistry())
        var tp=tps.getType("B")
        var nt=nm.toNominal(tp,x=>null);
        assert.isNotNull(nt);
        assert.equal(nt.superTypes().length,1);
        assert.equal(nt.allSuperTypes().length,3);
    });
    it("all properties", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: {type:"object","properties":{"z":"number"}},
                B: "A"

            }
        },ts.builtInRegistry())
        var tp=tps.getType("B")
        var nt=nm.toNominal(tp,x=>null);
        assert.isNotNull(nt);
        assert.equal(nt.allProperties().length,1);

    });
    it("print details", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: {type:"object","properties":{"z":"number"}},
                B: "A"

            }
        },ts.builtInRegistry())
        var tp=tps.getType("B")
        var nt=nm.toNominal(tp,x=>null);
        var details=nt.printDetails();
        assert.isTrue(details.indexOf("z : number[ValueType]")!=-1);
    });
    it("fixed facets acccess", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: {type:"object","properties":{"z":"number"},"facets": {"rr": "number"}},
                B: { type:"A",rr: 3}

            }
        },ts.builtInRegistry())
        var tp=tps.getType("B")
        var nt=nm.toNominal(tp,x=>null);

        assert.isTrue(nt.fixedFacets()["rr"]==3);
    });
    it("is External", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: {type:"{}"},
                B: { type:"A",rr: 3}

            }
        },ts.builtInRegistry())
        var tp=tps.getType("B")
        var nt=nm.toNominal(tp,x=>null);

        assert.isTrue(!nt.isExternal());
        assert.isTrue(nt.hasExternalInHierarchy());
    });
    it("nominal hierarchy 1 (Arrays)", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: "string[]"
            }
        },ts.builtInRegistry())
        var tp=tps.getType("A")
        var nt=nm.toNominal(tp,x=>null);
        var st=nt.allSuperTypes();
        assert.isTrue(st.length==2);
        assert.isTrue(nt.isArray())
        assert.isTrue(st[0].nameId()=="array");
        assert.isTrue(!st[0].isArray());
        assert.isTrue(st[1].nameId()=="any");
    });
    it("nominal hierarchy 2 (union)", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: "string|number"
            }
        },ts.builtInRegistry())
        var tp=tps.getType("A")
        var nt=nm.toNominal(tp,x=>null);
        var st=nt.allSuperTypes();
        assert.isTrue(st.length==2);
        assert.isTrue(nt.isUnion())
        assert.isTrue(st[0].nameId()=="union");
        assert.isTrue(st[1].nameId()=="any");
    });
    it("nominal hierarchy 3", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: { type: "string|number"}
            }
        },ts.builtInRegistry())
        var tp=tps.getType("A")
        var nt=nm.toNominal(tp,x=>null);
        var st=nt.allSuperTypes();
        assert.isTrue(st.length==2);
        assert.isTrue(nt.isUnion())
        assert.isTrue(st[0].nameId()=="union");
        assert.isTrue(st[1].nameId()=="any");
    });
    it("nominal hierarchy 4 (object)", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: { type: "object"}
            }
        },ts.builtInRegistry())
        var tp=tps.getType("A")
        var nt=nm.toNominal(tp,x=>null);

        var st=nt.allSuperTypes();
        assert.isTrue(st.length==2);
        assert.isTrue(st[0].nameId()=="object");
        assert.isTrue(st[1].nameId()=="any");
    });

    it("nominal validate", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: { type: "string"}
            }
        },ts.builtInRegistry())
        var tp=tps.getType("A")
        var nt=nm.toNominal(tp,x=>null);

        assert.isTrue(nt.validate(2).length==1);
        assert.isTrue(nt.validate("2").length==0);

    });

    it("genuine user defined type", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: { type: "object",properties:{ "x":"string"}}
            }
        },ts.builtInRegistry())
        var tp=tps.getType("A")
        var nt=nm.toNominal(tp,x=>null);

        var range=nt.properties()[0].range();
        assert.isTrue(!range.isGenuineUserDefinedType())
        assert.isTrue(nt.isGenuineUserDefinedType())
    });

    it("sub types information exists", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: { type: "object",properties:{ "x":"string"}},
                B: { type: "A"}
            }
        },ts.builtInRegistry())
        var tp=tps.getType("A")
        var nt=nm.toNominal(tp,x=>null);
        assert.isTrue(nt.subTypes().length==1);
        assert.isTrue(nt.subTypes()[0].nameId()=="B");

    });
    it("to nominal passes with intersting union types", function () {
        var tps = ps.parseJSONTypeCollection({
            types:{
                A: { type: "string"},
                B: { type: "string | A"},
                C: { type: ["B" ,"A"]}
            }
        },ts.builtInRegistry());
        var tp=tps.getType("C")
        var nt=nm.toNominal(tp,x=>null);
        assert.isTrue(nt.superTypes().length==2);
    });
});