require('../../support/test_helper');

var assert = require('../../support/assert');
var TestClient = require('../../support/test-client');
var dot = require('dot');
var debug = require('debug')('windshaft:cartodb:test');

describe('analysis-layers use cases', function() {


    var multitypeStyleTemplate = dot.template([
        "#points['mapnik::geometry_type'=1] {",
        "  marker-fill-opacity: {{=it._opacity}};",
        "  marker-line-color: #FFF;",
        "  marker-line-width: 0.5;",
        "  marker-line-opacity: {{=it._opacity}};",
        "  marker-placement: point;",
        "  marker-type: ellipse;",
        "  marker-width: 8;",
        "  marker-fill: {{=it._color}};",
        "  marker-allow-overlap: true;",
        "}",
        "#lines['mapnik::geometry_type'=2] {",
        "  line-color: {{=it._color}};",
        "  line-width: 2;",
        "  line-opacity: {{=it._opacity}};",
        "}",
        "#polygons['mapnik::geometry_type'=3] {",
        "  polygon-fill: {{=it._color}};",
        "  polygon-opacity: {{=it._opacity}};",
        "  line-color: #FFF;",
        "  line-width: 0.5;",
        "  line-opacity: {{=it._opacity}};",
        "}"
    ].join('\n'));


    function cartocss(color, opacity) {
        return multitypeStyleTemplate({
            _color: color || '#F11810',
            _opacity: Number.isFinite(opacity) ? opacity : 1
        });
    }

    function mapConfig(layers, dataviews, analysis) {
        return {
            version: '1.5.0',
            layers: layers,
            dataviews: dataviews || {},
            analysis: analysis || []
        };
    }

    function analysisDef(analysis) {
        return JSON.stringify(analysis);
    }

    var DEFAULT_MULTITYPE_STYLE = cartocss();

    var TILE_ANALYSIS_TABLES = { z: 14, x: 8023, y: 6177 };

    var useCases = [
        {
            desc: '1 mapnik layer',
            mapConfig: {
                version: '1.5.0',
                layers: [
                    {
                        type: 'cartodb',
                        options: {
                            sql: "select * from analysis_rent_listings",
                            cartocss: DEFAULT_MULTITYPE_STYLE,
                            cartocss_version: '2.3.0'
                        }
                    }
                ]
            }
        },

        {
            desc: '2 mapnik layers',
            mapConfig: mapConfig([
                {
                    type: 'cartodb',
                    options: {
                        sql: "select * from analysis_banks",
                        cartocss: cartocss('#2167AB'),
                        cartocss_version: '2.3.0'
                    }
                },
                {
                    type: 'cartodb',
                    options: {
                        sql: "select * from analysis_rent_listings",
                        cartocss: DEFAULT_MULTITYPE_STYLE,
                        cartocss_version: '2.3.0'
                    }
                }
            ])
        },

        {
            desc: 'rent listings + buffer over atm-machines',
            mapConfig: mapConfig([
                {
                    type: 'cartodb',
                    options: {
                        sql: "select * from analysis_rent_listings",
                        cartocss: DEFAULT_MULTITYPE_STYLE,
                        cartocss_version: '2.3.0'
                    }
                },
                {
                    type: 'analysis',
                    options: {
                        def: analysisDef({
                            "type": "buffer",
                            "params": {
                                "source": {
                                    "type": "source",
                                    "params": {
                                        "query": "select * from analysis_banks"
                                    }
                                },
                                "radius": 250
                            }
                        }),
                        cartocss: cartocss('black', 0.5)
                    }
                }
            ])
        },

        {
            desc: 'rent listings + point-in-polygon from buffer atm-machines and rent listings',
            mapConfig: mapConfig([
                {
                    type: 'cartodb',
                    options: {
                        sql: "select * from analysis_rent_listings",
                        cartocss: DEFAULT_MULTITYPE_STYLE,
                        cartocss_version: '2.3.0'
                    }
                },
                {
                    type: 'analysis',
                    options: {
                        def: analysisDef({
                            "type": "point-in-polygon",
                            "params": {
                                "pointsSource": {
                                    "type": "source",
                                    "params": {
                                        "query": "select * from analysis_rent_listings"
                                    }
                                },
                                "polygonsSource": {
                                    "type": "buffer",
                                    "params": {
                                        "source": {
                                            "type": "source",
                                            "params": {
                                                "query": "select * from analysis_banks"
                                            }
                                        },
                                        "radius": 250
                                    }
                                }
                            }
                        }),
                        cartocss: cartocss('green', 1.0)
                    }
                }
            ])
        },

        {
            desc: 'point-in-polygon from buffer atm-machines and rent listings + rent listings',
            mapConfig: mapConfig([
                {
                    type: 'analysis',
                    options: {
                        def: analysisDef({
                            "type": "point-in-polygon",
                            "params": {
                                "pointsSource": {
                                    "type": "source",
                                    "params": {
                                        "query": "select * from analysis_rent_listings"
                                    }
                                },
                                "polygonsSource": {
                                    "type": "buffer",
                                    "params": {
                                        "source": {
                                            "type": "source",
                                            "params": {
                                                "query": "select * from analysis_banks"
                                            }
                                        },
                                        "radius": 250
                                    }
                                }
                            }
                        }),
                        cartocss: cartocss('green', 1.0)
                    }
                },
                {
                    type: 'cartodb',
                    options: {
                        sql: "select * from analysis_rent_listings",
                        cartocss: DEFAULT_MULTITYPE_STYLE,
                        cartocss_version: '2.3.0'
                    }
                }
            ])
        },

        {
            desc: 'buffer + point-in-polygon from buffer atm-machines and rent listings + rent listings',
            mapConfig: mapConfig([
                {
                    type: 'cartodb',
                    options: {
                        sql: "select * from analysis_rent_listings",
                        cartocss: DEFAULT_MULTITYPE_STYLE,
                        cartocss_version: '2.3.0'
                    }
                },
                {
                    type: 'analysis',
                    options: {
                        def: analysisDef({
                            "type": "buffer",
                            "params": {
                                "source": {
                                    "type": "source",
                                    "params": {
                                        "query": "select * from analysis_banks"
                                    }
                                },
                                "radius": 300
                            }
                        }),
                        cartocss: cartocss('magenta', 0.5)
                    }
                },
                {
                    type: 'analysis',
                    options: {
                        def: analysisDef({
                            "type": "point-in-polygon",
                            "params": {
                                "pointsSource": {
                                    "type": "source",
                                    "params": {
                                        "query": "select * from analysis_rent_listings"
                                    }
                                },
                                "polygonsSource": {
                                    "type": "buffer",
                                    "params": {
                                        "source": {
                                            "type": "source",
                                            "params": {
                                                "query": "select * from analysis_banks"
                                            }
                                        },
                                        "radius": 300
                                    }
                                }
                            }
                        }),
                        cartocss: cartocss('green', 1.0)
                    }
                }
            ])
        },

        {
            skip: true,
            desc: 'buffer + point-in-polygon from buffer atm-machines and rent listings + rent listings',
            mapConfig: mapConfig([
                {
                    type: 'cartodb',
                    options: {
                        "source": { id: "a" },
                        "cartocss": DEFAULT_MULTITYPE_STYLE,
                        "cartocss_version": "2.3.0"
                    }
                },
                {
                    type: 'cartodb',
                    options: {
                        "source": { id: "b1" },
                        "cartocss": cartocss('green', 1.0),
                        "cartocss_version": "2.3.0"
                    }
                },
                {
                    type: 'cartodb',
                    options: {
                        "source": { id: "b2" },
                        "cartocss": cartocss('magenta', 0.5),
                        "cartocss_version": "2.3.0"
                    }
                }
            ],
            [
                {
                    id: "b2",
                    options: {
                        def: analysisDef({
                            "type": "count-in-polygon",
                            "id": "a0",
                            "params": {
                                "columnName": 'count_airbnb',
                                "pointsSource": {
                                    "type": "source",
                                    "params": {
                                        query: "select * from analysis_rent_listings"
                                    },
                                    dataviews: {
                                        price_histogram: {
                                            type: 'histogram',
                                            options: {
                                                column: 'price'
                                            }
                                        }
                                    }
                                },
                                "polygonsSource": {
                                    "id": "b1",
                                    "type": "buffer",
                                    "params": {
                                        "source": {
                                            "id": "b0",
                                            "type": "source",
                                            "params": {
                                                query: "select * from analysis_banks"
                                            }
                                        },
                                        "radius": 250
                                    },
                                    dataviews: {
                                        bank_category: {
                                            type: 'aggregation',
                                            options: {
                                                column: 'bank'
                                            }
                                        }
                                    }
                                }
                            },
                            dataviews: {
                                count_histogram: {
                                    type: 'histogram',
                                    options: {
                                        column: 'count_airbnb'
                                    }
                                }
                            }
                        }),
                        cartocss: cartocss('green', 1.0)
                    }
                }
            ])
        },

        {
            skip: true,
            desc: 'I. Distribution centers',
            mapConfig: mapConfig(
                // layers
                [
                    {
                        type: 'cartodb',
                        options: {
                            "source": { id: "b0" },
                            "cartocss": [
                                "#distribution_centers {",
                                "  marker-fill-opacity: 1.0;",
                                "  marker-line-color: #FFF;",
                                "  marker-line-width: 0.5;",
                                "  marker-line-opacity: 0.7;",
                                "  marker-placement: point;",
                                "  marker-type: ellipse;",
                                "  marker-width: 8;",
                                "  marker-fill: blue;",
                                "  marker-allow-overlap: true;",
                                "}"
                            ].join('\n'),
                            "cartocss_version": "2.3.0"
                        }
                    },
                    {
                        type: 'cartodb',
                        options: {
                            "source": { id: "a0" },
                            "cartocss": [
                                "#shops {",
                                "  marker-fill-opacity: 1.0;",
                                "  marker-line-color: #FFF;",
                                "  marker-line-width: 0.5;",
                                "  marker-line-opacity: 0.7;",
                                "  marker-placement: point;",
                                "  marker-type: ellipse;",
                                "  marker-width: 8;",
                                "  marker-fill: red;",
                                "  marker-allow-overlap: true;",
                                "}"
                            ].join('\n'),
                            "cartocss_version": "2.3.0"
                        }
                    },
                    {
                        type: 'cartodb',
                        options: {
                            "source": { id: "a1" },
                            "cartocss": [
                                "#routing {",
                                "  line-color: ramp([routing_time], colorbrewer(Reds));",
                                "  line-width: ramp([routing_time], 2, 8);",
                                "  line-opacity: 1.0;",
                                "}"
                            ].join('\n'),
                            "cartocss_version": "2.3.0"
                        }
                    }
                ],
                // dataviews
                {
                    distribution_center_name_category: {
                        source: { id: 'b0' },
                        type: 'aggregation',
                        options: {
                            column: 'name'
                        }
                    },
                    time_histogram: {
                        source: { id: 'a1' },
                        type: 'histogram',
                        options: {
                            column: 'routing_time'
                        }
                    },
                    distance_histogram: {
                        source: { id: 'a1' },
                        type: 'histogram',
                        options: {
                            column: 'routing_distance'
                        }
                    }
                },
                // analysis
                [
                    {
                        id: 'a1',
                        type: 'routing-n-to-n',
                        params: {
                            // distanceColumn: 'routing_distance',
                            // timeColumn: 'routing_time',
                            originSource: {
                                id: 'b0',
                                type: 'source',
                                params: {
                                    query: 'select * from distribution_centers'
                                }
                            },
                            destinationSource: {
                                id: 'a0',
                                type: 'source',
                                params: {
                                    query: 'select * from shops'
                                }
                            }
                        }
                    }
                ]
            )
        },

        {
            skip: true,
            desc: 'II. Population analysis',
            mapConfig: mapConfig(
            // layers
            [
                {
                    type: 'cartodb',
                    options: {
                        "source": { id: "a2" },
                        "cartocss": [
                            "#count_in_polygon {",
                            "  polygon-opacity: 1.0",
                            "  line-color: #FFF;",
                            "  line-width: 0.5;",
                            "  line-opacity: 0.7",
                            "  polygon-fill: ramp([estimated_people], colorbrewer(Reds));",
                            "}"
                        ].join('\n'),
                        "cartocss_version": "2.3.0"
                    }
                },
                {
                    type: 'cartodb',
                    options: {
                        "source": { id: "a0" },
                        "cartocss": DEFAULT_MULTITYPE_STYLE,
                        "cartocss_version": "2.3.0"
                    }
                }
            ],
            // dataviews
            {
                total_population_formula: {
                    "source": { id: "a3" },
                    type: 'formula',
                    options: {
                        column: 'total_population',
                        operation: 'sum'
                    }
                },
                people_histogram: { // this injects a range filter at `a2` node output
                    "source": { id: "a2" },
                    type: 'histogram',
                    options: {
                        column: 'estimated_people'
                    }
                },
                subway_line_category: { // this injects a category filter at `a0` node output
                    "source": { id: "a0" },
                    type: 'aggregation',
                    options: {
                        column: 'subway_line'
                    }
                }
            },
            // analysis
            [
                {
                    id: 'a3',
                    // this will union the polygons, produce just one polygon, and calculate the total population for it
                    type: 'total-population',
                    params: {
                        columnName: 'total_population',
                        source: {
                            id: 'a2',
                            type: 'estimated-population',
                            params: {
                                columnName: 'estimated_people',
                                source: {
                                    id: 'a1',
                                    type: 'trade-area',
                                    params: {
                                        source: {
                                            "id": "a0",
                                            "type": "source",
                                            "params": {
                                                query: "select * from subway_stops"
                                            }
                                        },
                                        kind: 'walk',
                                        time: 300
                                    }
                                }
                            }
                        }
                    }
                }
            ])
        },

        {
            skip: true,
            desc: 'III. Point in polygon',
            mapConfig: mapConfig(
                // layers
                [
                    {
                        type: 'cartodb',
                        options: {
                            "source": { id: "a1" },
                            "cartocss": [
                                "#count_in_polygon {",
                                "  polygon-opacity: 1.0",
                                "  line-color: #FFF;",
                                "  line-width: 0.5;",
                                "  line-opacity: 0.7",
                                "  polygon-fill: ramp([count_people], colorbrewer(Reds));",
                                "}"
                            ].join('\n'),
                            "cartocss_version": "2.3.0"
                        }
                    }
                ],
                // dataviews
                {
                    age_histogram: {
                        "source": { id: "a0" },
                        type: 'histogram',
                        options: {
                            column: 'age'
                        }
                    },
                    income_histogram: {
                        "source": { id: "a0" },
                        type: 'histogram',
                        options: {
                            column: 'income'
                        }
                    },
                    gender_category: {
                        "source": { id: "a0" },
                        type: 'aggregation',
                        options: {
                            column: 'gender'
                        }
                    }
                },
                // analysis
                [
                    {
                        "id": "a1",
                        "type": "count-in-polygon",
                        "params": {
                            "columnName": 'count_people',
                            "pointsSource": {
                                "id": 'a0',
                                "type": "source",
                                "params": {
                                    query: "select the_geom, age, gender, income from people"
                                }
                            },
                            "polygonsSource": {
                                "id": "b0",
                                "type": "source",
                                "params": {
                                    query: "select * from postal_codes"
                                }
                            }
                        }
                    }
                ]
            )
        }

    ];

    useCases.forEach(function(useCase, imageIdx) {
        if (!!useCase.skip) {
            debug(JSON.stringify(useCase.mapConfig, null, 4));
        }
        it.skip('should implement use case: "' + useCase.desc + '"', function(done) {

            var testClient = new TestClient(useCase.mapConfig, 1234);

            var tile = useCase.tile || TILE_ANALYSIS_TABLES;

            testClient.getTile(tile.z, tile.x, tile.y, function(err, res, image) {
                assert.ok(!err, err);

                image.save('/tmp/tests/' + imageIdx + '---' + useCase.desc.replace(/\s/g, '-') + '.png');

                assert.equal(image.width(), 256);

                testClient.drain(done);
            });
        });
    });
});
