/* Minification failed. Returning unminified contents.
(2475,26-27): run-time error JS1014: Invalid character: `
(2475,32-33): run-time error JS1004: Expected ';': :
(2481,69-70): run-time error JS1004: Expected ';': :
(2481,81-82): run-time error JS1195: Expected expression: ,
(2481,91-92): run-time error JS1004: Expected ';': :
(2481,101-102): run-time error JS1195: Expected expression: ]
(2485,18-19): run-time error JS1197: Too many errors. The file might not be a JavaScript file: .
(1951,1-29): run-time error JS1301: End of file encountered before function is properly closed: function formatPopup(search)
(2491,9-10): run-time error JS1002: Syntax error: }
(2495,9-11): run-time error JS1197: Too many errors. The file might not be a JavaScript file: if
 */
// level at which layers switch from subunits to plume
APP.propToPlumeScale = 3000;

// order of this object controls layer visibility on map, first layer in array is on bottom
APP.layerConfig = [
    {
        id: 0,
        name: 'healthDept',
        add: false,
        applyDefExp: false,
        toggleVisibility: false,
        setMin: false,
        setMax: false
    },
    {
        id: 1,
        name: 'rightsOfWay',
        title: 'Rights of Way',
        add: true,
        visible: false,
        legendEnabled: false,
        applyDefExp: false,
        toggleVisibility: true,
        opacity: 0.6,
        setMax: false,
        setMin: true,
        minScale: APP.propToPlumeScale
    },
    {
        id: 8,
        name: 'homeSoilTestingParcels',
        add: true,
        visible: false,
        applyDefExp: false,
        toggleVisibility: false,
        setMin: false,
        setMax: false
    },
    {
        id: 7,
        name: 'homeSoilTestingUnits',
        add: true,
        visible: false,
        legendEnabled: true,
        title: 'Home Soil Testing',
        applyDefExp: false,
        toggleVisibility: false,
        setMin: false,
        setMax: false
    },
    {
        id: 15,
        name: 'plume',
        add: true,
        visible: true,        
        legendEnabled: false,
        title: 'Predicted Arsenic Concentration',
        applyDefExp: false,
        toggleVisibility: false,
        maxScale: APP.propToPlumeScale,
        setMin: false,
        setMax: true
    },
    {
        id: 2,
        name: 'properties',
        add: true,
        visible: false,
        legendEnabled: true,
        title: 'Property Status',
        applyDefExp: false,
        toggleVisibility: false,
        opacity: 0.6,
        setMin: false,
        setMax: false,
        labelingInfo: [{
            labelExpression: '[EcologyIdentifier]',
            labelPlacement: "always-horizontal",
            symbol: {
                type: "text",
                color: [255, 255, 255, 1],
                haloColor: "black",
                haloSize: 1,
                font: {
                    size: 11,
                    weight: "bold"
                }
            },
            minScale: 4000
        }]
    },
    {
        id: 2,
        name: 'propertiesJustOutlines',
        add: true,
        visible: true,
        legendEnabled: false,
        applyDefExp: false,
        toggleVisibility: false,
        renderer: {
            type: "simple",
            symbol: {
                type: "simple-fill",
                color: [0, 0, 0, 0],
                outline: {
                    color: [220, 231, 241, 1],
                    width: "0.5px"
                }
            }
        },
        setMin: true,
        setMax: false,
        minScale: APP.propToPlumeScale,
        labelsVisible: true,
        labelingInfo: [{
            where: 'Name is not null',
            labelExpression: '[Name]',
            labelPlacement: "always-horizontal",
            symbol: {
                type: "text",
                color: [134, 188, 161, 1],
                haloColor: [50, 72, 55, 1],
                haloSize: 1,
                font: {
                    size: 14,
                    weight: "bold"
                }
            },
            minScale: APP.propToPlumeScale
        }]
    },
    {// SSP boundary for visual
        id: 9,
        name: 'SoilSafteyProgramLine',
        add: true,
        visible: true,
        legendEnabled: false,
        applyDefExp: false,
        toggleVisibility: false,
        labelsVisible: true,
        labelingInfo: [{
            labelExpression: '"Soil Safety Program Boundary"',
            labelPlacement: 'above-along',
            symbol: {
                type: "text",
                color: [115, 178, 115, 1],
                haloColor: [210, 210, 210, 1],
                haloSize: 1,
                font: {
                    size: 10,
                    weight: "bold"
                }
            }
        }],
        maxScale: APP.propToPlumeScale,
        minScale: 80000,
        setMin: false,
        setMax: true
    },
    {// SSP boundary for use in identify
        id: 10,
        name: 'SoilSafetyProgramBoundary',
        add: true,
        visible: false,
        legendEnabled: false,
        setMin: false,
        setMax: false
    },
    {
        id: 11,
        name: 'YardServiceAreaBoundary',
        add: true,
        visible: true,
        legendEnabled: false,
        title: 'Yard Program Service Area',
        applyDefExp: false,
        toggleVisibility: false,
        maxScale: APP.propToPlumeScale,
        minScale: 80000,
        labelsVisible: true,
        setMin: false,
        setMax: true
    },
    {
        id: 13,
        name: 'everett',
        add: true,
        visible: true,
        legendEnabled: false,
        applyDefExp: false,
        toggleVisibility: false,
        renderer: {
            type: "simple",
            symbol: {
                type: "simple-fill",
                color: [0, 0, 0, 0],
                outline: {
                    style: "dash",
                    width: 2,
                    color: [0, 132, 168, 1]
                }
            }
        },
        opactiy: 0.5,
        setMin: false,
        setMax: false
    },
    {
        id: 12,
        name: 'orchardLands',
        add: true,
        visible: false,
        legendEnabled: false,
        applyDefExp: false,
        toggleVisibility: false,
        setMin: false,
        setMax: false
    },
    {
        id: 14,
        name: 'upperColumbia',
        add: true,
        visible: true,
        legendEnabled: false,
        applyDefExp: false,
        toggleVisibility: false,
        renderer: {
            type: "simple",
            symbol: {
                type: "simple-fill",
                color: [0, 0, 0, 0],
                outline: {
                    style: "dash",
                    width: 2,
                    color: [0, 132, 168, 1]
                }
            }
        },
        opactiy: 0.5,
        setMin: false,
        setMax: false
    },
    {
        id: 5,
        name: 'subunitsArsenic',
        add: true,
        visible: false,
        legendEnabled: true,
        title: 'Arsenic (parts per million - ppm)',
        opacity: .7,
        applyDefExp: true,
        toggleVisibility: true,
        labelsVisible: true,
        setMin: true,
        minScale: APP.propToPlumeScale,
        setMax: false
    },
    {
        id: 6,
        name: 'subunitsLead',
        add: true,
        visible: false,
        legendEnabled: true,
        title: 'Lead (parts per million - ppm)',
        opacity: .7,
        applyDefExp: true,
        toggleVisibility: false,
        setMin: true,
        minScale: APP.propToPlumeScale,
        labelsVisible: true,
        setMax: false
    },
    {
        id: 4,
        name: 'subunitsJustOutlines',
        add: true,
        visible: false,
        legendEnabled: false,
        applyDefExp: true,
        toggleVisibility: false,
        setMin: true,
        minScale: APP.propToPlumeScale,
        opactiy: 0.5,
        renderer: {
            type: "simple",
            symbol: {
                type: "simple-fill",
                color: [0, 0, 0, 0],
                outline: {
                    color: [0, 0, 0, 1],
                    width: "2px"
                }
            }
        },
        setMax: false
    },
    {
        id: 17,
        name: 'vcpProperties',
        add: true,
        visible: false,
        legendEnabled: true,
        title: 'Voluntary Cleanup Program',
        applyDefExp: false,
        toggleVisibility: false,
        setMin: true,
        minScale: APP.propToPlumeScale,
        renderer: {
            type: "simple",
            symbol: {
                type: "simple-fill",
                color: [0, 0, 0, 0],
                outline: {
                    color: [0, 197, 255, 1],
                    width: "4px"
                }
            }
        },
        setMax: false
    },
    {
        id: 3,
        name: 'excavation',
        add: true,
        visible: false,
        legendEnabled: true,
        title: 'Action Complete (Soil Replacement)',
        applyDefExp: true,
        toggleVisibility: false,
        setMin: true,
        minScale: APP.propToPlumeScale,
        setMax: false
    },
    {
        id: 18,
        name: 'plumeBoundary',
        add: false,
        visible: false,
        legendEnabled: false,
        applyDefExp: false,
        toggleVisibility: false
    },
    {// Yard Program boundary with label
        id: 19,
        name: 'YardProgramLine',
        add: true,
        visible: true,
        legendEnabled: false,
        applyDefExp: false,
        toggleVisibility: false,
        labelsVisible: true,
        labelingInfo: [{
            labelExpression: '"Yard Program Boundary"',
            labelPlacement: 'above-along',
            symbol: {
                type: "text",
                color: [122, 204, 196, 1],
                font: {
                    size: 10,
                    weight: "bold"
                }
            }
        }],
        maxScale: APP.propToPlumeScale,
        minScale: 80000,
        setMin: false,
        setMax: true
    },
    {
        id: 20,
        name: 'hstBoundary',
        add: true,
        visible: false,
        legendEnabled: false,
        applyDefExp: false,
        toggleVisibility: false
    },
    {
        id: 21,
        name: 'orchards',
        title: 'Former Orchards',
        add: true,
        visible: false,
        legendEnabled: true,
        applyDefExp: false,
        toggleVisibility: false,
        renderer: {
            type: 'simple',
            symbol: {
                type: 'simple-fill',
                color: [251, 101, 66, 0.3],
                outline: {
                    style: 'dash',
                    width: 1.5,
                    color: [251, 101, 66, 1]
                }
            }
        }
    },
    {
        id: 22,
        name: 'sampledOrchardProperties',
        add: true,
        visible: true,
        legendEnabled: false
    },
    {
        id: 24,
        title: 'Arsenic Samples',
        name: 'centralSamplesArsenic',
        add: true,
        visible: false,
        legendEnabled: true,
        minScale: 200000,
        sublayers: [
            {// most zoomed in layer with labels
                id: 23,
                labelsVisible: true,
                labelingInfo: [{
                    labelExpression: 'Round([Arsenic_ppm], 1) concat " ppm"',
                    labelPlacement: "always-horizontal",
                    minScale: 3000,
                    symbol: {
                        type: "text",
                        color: [255, 255, 255, 1],
                        haloColor: "black",
                        haloSize: 1,
                        font: {
                            size: 14,
                            weight: "normal"
                        }
                    }
                }],
                renderer: {
                    type: "class-breaks",
                    field: 'Arsenic_ppm',
                    classBreakInfos: [
                        {
                            minValue: 0,
                            maxValue: 20,
                            label: '< 20 ppm',
                            symbol: {
                                type: "simple-marker",
                                size: 20,
                                color: [117, 174, 209, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "2px"
                                }
                            }
                        },
                        {
                            minValue: 20,
                            maxValue: 5000,
                            label: '> 20 ppm',
                            symbol: {
                                type: "simple-marker",
                                size: 20,
                                color: [168, 0, 0, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "2px"
                                }
                            }
                        }
                    ]
                },
                minScale: 15000,
                title: 'Cleanup Level: 20 ppm'
            },
            {// middle layer
                id: 23,
                renderer: {
                    type: "class-breaks",
                    field: 'Arsenic_ppm',
                    classBreakInfos: [                        
                        {
                            minValue: 0,
                            maxValue: 20,
                            label: '< 20 ppm',
                            symbol: {
                                type: "simple-marker",
                                size: 15,
                                color: [117, 174, 209, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "2px"
                                }
                            }
                        },
                        {
                            minValue: 20,
                            maxValue: 10000000,
                            label: '> 20 ppm',
                            symbol: {
                                type: "simple-marker",
                                size: 15,
                                color: [168, 0, 0, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "2px"
                                }
                            }
                        }
                    ]
                },
                maxScale: 15000,
                minScale: 100000,
                title: 'Cleanup Level: 20 ppm'
            },
            {//most zoomed out layer
                id: 23,
                renderer: {
                    type: "class-breaks",
                    field: 'Arsenic_ppm',
                    classBreakInfos: [                        
                        {
                            minValue: 0,
                            maxValue: 20,
                            label: '< 20 ppm',
                            symbol: {
                                type: "simple-marker",
                                size: 10,
                                color: [117, 174, 209, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "1px"
                                }
                            }
                        },
                        {
                            minValue: 20,
                            maxValue: 10000000,
                            label: '> 20 ppm',
                            symbol: {
                                type: "simple-marker",
                                size: 10,
                                color: [168, 0, 0, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "1px"
                                }
                            }
                        }
                    ]
                },
                maxScale: 100000,
                minScale: 200000,
                title: 'Cleanup Level: 20 ppm'
            }
        ]
    },
    {
        id: 25,
        name: 'centralSamplesLead',
        title: 'Lead Samples',
        add: true,
        visible: false,
        legendEnabled: true,
        minScale: 200000,
        sublayers: [
            {
                id: 23,
                labelsVisible: true,
                labelingInfo: [{
                    labelExpression: 'Round([Lead_ppm],1) concat " ppm"',
                    labelPlacement: "always-horizontal",
                    minScale: 3000,
                    symbol: {
                        type: "text",
                        color: [255, 255, 255, 1],
                        haloColor: "black",
                        haloSize: 1,
                        font: {
                            size: 14,
                            weight: "normal"
                        }
                    }
                }],
                renderer: {
                    type: "class-breaks",
                    field: 'Lead_ppm',
                    classBreakInfos: [
                        {
                            minValue: 0,
                            maxValue: 250,
                            label: '< 250 ppm',
                            symbol: {
                                type: "simple-marker",
                                style: 'square',
                                size: 20,
                                color: [117, 174, 209, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "2px"
                                }
                            }
                        },                        
                        {
                            minValue: 250,
                            maxValue: 1000000000,
                            label: '> 250 ppm',
                            symbol: {
                                type: "simple-marker",
                                style: 'square',
                                size: 20,
                                color: [168, 0, 0, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "2px"
                                }
                            }
                        }
                    ]
                },
                minScale: 15000,
                title: 'Cleanup Level: 250 ppm'
            },
            {
                id: 23,
                renderer: {
                    type: "class-breaks",
                    field: 'Lead_ppm',
                    classBreakInfos: [
                        {
                            minValue: 0,
                            maxValue: 250,
                            label: '< 250 ppm',
                            symbol: {
                                type: "simple-marker",
                                style: 'square',
                                size: 15,
                                color: [117, 174, 209, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "2px"
                                }
                            }
                        },                        
                        {
                            minValue: 250,
                            maxValue: 1000000000,
                            label: '> 250 ppm',
                            symbol: {
                                type: "simple-marker",
                                style: 'square',
                                size: 15,
                                color: [168, 0, 0, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "2px"
                                }
                            }
                        }
                    ]
                },
                maxScale: 15000,
                minScale: 100000,
                title: 'Cleanup Level: 250 ppm'
            },
            {
                id: 23,
                renderer: {
                    type: "class-breaks",
                    field: 'Lead_ppm',
                    classBreakInfos: [
                        {
                            minValue: 0,
                            maxValue: 250,
                            label: '< 250 ppm',
                            symbol: {
                                type: "simple-marker",
                                style: 'square',
                                size: 10,
                                color: [117, 174, 209, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "2px"
                                }
                            }
                        },
                        {
                            minValue: 250,
                            maxValue: 1000000000,
                            label: '> 250 ppm',
                            symbol: {
                                type: "simple-marker",
                                style: 'square',
                                size: 10,
                                color: [168, 0, 0, 1],
                                outline: {
                                    color: [255, 255, 255, 1],
                                    width: "2px"
                                }
                            }
                        }
                    ]
                },
                maxScale: 100000,
                minScale: 200000,
                title: 'Cleanup Level: 250 ppm'
            }
        ]

    }
];


APP.layerIds = {
    subunitsArsenic: APP.layerConfig.find(function (el) { return el.name === 'subunitsArsenic'; }).id,
    subunitsLead: APP.layerConfig.find(function (el) { return el.name === 'subunitsLead'; }).id,
    subunitOutlines: APP.layerConfig.find(function (el) { return el.name === 'subunitsJustOutlines'; }).id,
    excavation: APP.layerConfig.find(function (el) { return el.name === 'excavation'; }).id,
    properties: APP.layerConfig.find(function (el) { return el.name === 'properties'; }).id,
    hstParcels: APP.layerConfig.find(function (el) { return el.name === 'homeSoilTestingParcels'; }).id,
    hstUnits: APP.layerConfig.find(function (el) { return el.name === 'homeSoilTestingUnits'; }).id,
    healthDept: APP.layerConfig.find(function (el) { return el.name === 'healthDept'; }).id,
    vcp: APP.layerConfig.find(function (el) { return el.name === 'vcpProperties'; }).id,
    plume: APP.layerConfig.find(function (el) { return el.name === 'plume'; }).id,
    plumeBoundary: APP.layerConfig.find(function (el) { return el.name === 'plumeBoundary'; }).id,
    rightsOfWay: APP.layerConfig.find(function (el) { return el.name === 'rightsOfWay'; }).id,
    upperColumbia: APP.layerConfig.find(function (el) { return el.name === 'upperColumbia'; }).id,
    everett: APP.layerConfig.find(function (el) { return el.name === 'everett'; }).id,
    hstBoundary: APP.layerConfig.find(function (el) { return el.name === 'hstBoundary'; }).id,
    sspBoundary: APP.layerConfig.find(function (el) { return el.name === 'SoilSafetyProgramBoundary'; }).id,
    yardBoundary: APP.layerConfig.find(function (el) { return el.name === 'YardServiceAreaBoundary'; }).id,
    orchardLands: APP.layerConfig.find(function (el) { return el.name === 'orchardLands'; }).id,
    orchards: APP.layerConfig.find(function (el) { return el.name === 'orchards'; }).id,
    sampledOrchardProperties: APP.layerConfig.find(function (el) { return el.name === 'sampledOrchardProperties'; }).id,
    centralSamplesArsenic: APP.layerConfig.find(function (el) { return el.name === 'centralSamplesArsenic'; }).id,
    centralSamplesLead: APP.layerConfig.find(function (el) { return el.name === 'centralSamplesLead'; }).id
};

APP.applyDefExpLayers = APP.layerConfig.filter(function (layer) {
    return layer.applyDefExp === true;
});

//--------------------------------------------------------//
// contact/popup data
//--------------------------------------------------------//
APP.urls = {
    dirtAlert: 'https://ecology.wa.gov/Spills-Cleanup/Contamination-cleanup/Dirt-Alert-program/Healthy-actions',
    soilReplacement: 'https://ecology.wa.gov/Spills-Cleanup/Contamination-cleanup/Cleanup-sites/Toxic-cleanup-sites/Tacoma-smelter/soil-replacement',
    soilSampling: 'https://ecology.wa.gov/Spills-Cleanup/Contamination-cleanup/Dirt-Alert-program/Soil-sampling',
    yardProgram: 'https://ecology.wa.gov/Spills-Cleanup/Contamination-cleanup/Cleanup-sites/Toxic-cleanup-sites/Tacoma-smelter/Yard-cleanup-program',
    everett: 'https://ecology.wa.gov/Spills-Cleanup/Contamination-cleanup/Cleanup-sites/Toxic-cleanup-sites/Everett-smelter',
    healthyActions: 'https://ecology.wa.gov/Spills-Cleanup/Contamination-cleanup/Dirt-Alert-program/Healthy-actions',
    upperColumbiaGSP: 'https://apps.ecology.wa.gov/cleanupsearch/site/12125',
    pierceMainUrl: 'https://www.tpchd.org/healthy-homes/dirt-alert-tacoma-smelter-plume',
    pierceAccessAgreement: 'https://apps.ecology.wa.gov/publications/documents/ecy070672.pdf',
    kingMainUrl: 'https://kingcounty.gov/depts/health/environmental-health/toxins-air-quality/arsenic-lead/tacoma-smelter-plume.aspx',
    kingHstAccessAgreement: 'https://apps.ecology.wa.gov/cleanupsearch/DocViewer.ashx?did=62841',
    kingYardAccessAgreement: 'https://apps.ecology.wa.gov/cleanupsearch/DocViewer.ashx?did=19238',
    orchardLands: 'https://ecology.wa.gov/Spills-Cleanup/Contamination-cleanup/Cleanup-sites/Toxic-cleanup-sites/Former-orchard-lands'
};

APP.contacts = {
    dev: {
        message: 'Planning a development, remodel, or large landscaping project? Talk to our Technical Assistance Coordinator',
        name: 'Diana Ison – Dept. of Ecology',
        title: 'Technical Assistance Coordinator',
        phone: '(360) 999-9593',
        email: 'Diana.Ison@ecy.wa.gov',        
        url: 'https://ecology.wa.gov/Spills-Cleanup/Contamination-cleanup/Cleanup-sites/Toxic-cleanup-sites/Tacoma-smelter/Technical-assistance',
        open: false
    },
    ssp: {
        message: 'Learn about sampling and cleanup information for Schools, Parks, and Camps',
        name: 'Justin Zakoren – Dept. of Ecology',
        title: 'Yard Program Remediation Manager',
        phone: '(360)-407-6790',
        email: 'Justin.Zakoren@ecy.wa.gov',
        url: 'https://ecology.wa.gov/Spills-Cleanup/Contamination-cleanup/Cleanup-sites/Toxic-cleanup-sites/Tacoma-smelter/Soil-safety-program',
        open: false
    },
    yard: {
        message: 'Learn more about sampling and soil replacement on your property',
        name: 'Justin Zakoren – Dept. of Ecology',
        title: 'Yard Program Remediation Manager',
        phone: '(360)-407-6790',
        email: 'Justin.Zakoren@ecy.wa.gov',
        url: APP.urls.yardProgram,
        open: false
    },
    general: {
        message: 'General Information - Tacoma Smelter Plume',
        name: 'Justin Zakoren – Dept. of Ecology',
        title: 'Yard Program Remediation Manager',
        phone: '(360)-407-6790',
        email: 'Justin.Zakoren@ecy.wa.gov',
        url: APP.urls.soilSampling,
        open: false
    },
    ucr: {
        message: 'Learn more about sampling and cleanup work in the Upper Columbia River Lake Roosevelt Cleanup Site',
        name: 'Erika Beresovoy – Dept. of Ecology',
        title: 'Public Involvement Coordinator',
        phone: '(509) 385-2290',
        email: 'Erika.Beresovoy@ecy.wa.gov',
        url: APP.urls.soilSampling,
        open: false
    },
    everett: {
        message: 'Learn more about sampling and soil replacement on your property',
        name: 'Sandra Matthews – Dept. of Ecology',
        title: 'Project Manager',
        phone: '(425) 223-1999',
        email: 'Sandra.Matthews@ecy.wa.gov',
        url: APP.urls.soilSampling,
        open: false
    },
    orchard: {
        message: 'Learn about past land use that may affect your property',
        name: 'Rhonda Luke – Dept. of Ecology',
        title: 'Former Orchards Project Coordinator',
        phone: '(509) 406-6931',
        email: 'FormerOrchards@ecy.wa.gov',
        url: APP.urls.orchardLands,
        open: false
    }
};  ;

require([
    'esri/Map',
    'esri/Graphic',
    'esri/layers/GraphicsLayer',
    'esri/tasks/IdentifyTask',
    'esri/tasks/support/IdentifyParameters',
    'esri/tasks/Locator',
    'esri/tasks/QueryTask',
    'esri/tasks/support/Query',
    'esri/views/MapView',
    'esri/layers/MapImageLayer',
    'esri/layers/ImageryLayer',
    'esri/layers/BingMapsLayer',
    'esri/Basemap',
    'esri/widgets/Search',
    'esri/widgets/Zoom',
    'esri/widgets/Legend',
    'esri/widgets/Locate',
    'esri/widgets/BasemapToggle',
    'esri/geometry/Extent',
    'esri/geometry/Point',
    "esri/core/watchUtils",
    'esri/core/Accessor',
    'dojo/dom',
    'dojo/domReady!'
],
    function (
        Map,
        Graphic,
        GraphicsLayer,
        IdentifyTask,
        IdentifyParameters,
        Locator,
        QueryTask,
        Query,
        MapView,
        MapImageLayer,
        ImageryLayer,
        BingMapsLayer,
        Basemap,
        Search,
        Zoom,
        Legend,
        Locate,
        BasemapToggle,
        Extent,
        Point,
        watchUtils,
        Accessor,
        dom
    ) {

        if (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > -1) {
            $('#ie11-warning-modal').show();
            $('.modal-overlay').show();
            gtag('event', 'IE Detected');
        }

        // determine env for display of property status button
        APP.test = window.location.host === 'apps.ecology.wa.gov' ? false : true;

        // select active nav in nav bar 
        $('.map-mode').removeClass('active');
        let active = $('.map-mode').filter(function () {
            return $(this).data('mode') === APP.mode;
        });
        active.addClass('active');
        
        // create mapimagelayer from layer config
        APP.smelterService = new MapImageLayer({
            url: APP.mapservice,
            title: null,
            sublayers: APP.layerConfig.filter(function (layer) {
                return layer.add === true;
            }),
            id: 'mapservice'
        });

        // graphics layer for subunit hover highlight graphic
        let subunitsGraphicsLayer = new GraphicsLayer({
            id: 'subunitsGraphics'
        });

        // set map and view parameters
        APP.map = new Map({
            basemap: 'topo',
            layers: [APP.smelterService, subunitsGraphicsLayer]
        });

        // set up view
        APP.view = new MapView({
            container: 'viewDiv',
            map: APP.map,
            constraints: {
                rotationEnabled: false,
                maxZoom: 19 // Bing imagery throws errors at zoom > 19 in rural areas
            }
        });
        APP.view.ui.padding = 10;
        
        // create Bing basemap
        let bingKey = "Aj9eK_pOHnO3rGAxM1Ujkcf7SbewgXkWcbuwi2x-qA_PEHeOgEHN__68U4sDpJ7l";
        var bingMapsLayer = new BingMapsLayer({ key: bingKey, style: 'hybrid', id: 'bmHybrid' });
        let bingBasemap = new Basemap({
            baseLayers: [bingMapsLayer],
            referenceLayers: [bingMapsLayer],
            title: 'Imagery',
            thumbnailUrl: 'https://fortress.wa.gov/ecy/gisresources/TCP/dirtalert/AerialImageryBasemap.png'            
        });

        // create basemap toggle, add to UI
        let basemapToggle = new BasemapToggle({
            view: APP.view,
            nextBasemap: bingBasemap
        });

        // when map has finished moving, check scale and switch to correct basemap
        // imagery if zoomed in, topographic if zoomed out
        watchUtils.whenTrue(APP.view, 'stationary', function () {
            watchUtils.whenFalse(APP.view, 'updating', function () {
                if (APP.view.scale < APP.propToPlumeScale && APP.map.basemap.title === 'Topographic') {
                    basemapToggle.toggle();
                } else if (APP.view.scale > APP.propToPlumeScale && APP.map.basemap.title === 'Imagery') {
                    basemapToggle.toggle();
                }
            });
        });

        // 
        // assign renderer to be blue dashed outline for areas not in APP.mode
        let renderer = {
            type: "simple",
            symbol: {
                type: "simple-fill",
                color: [0, 0, 0, 0],
                outline: {
                    style: "dash",
                    width: 2,
                    color: [0, 132, 168, 1]
                }
            }
        };

        //
        // determine start zoom and extent
        let start = {};
        

        // query url for location
        let searchparams = new URLSearchParams(window.location.search);

        //
        // hide metal toggle button for orchard lands
        $('#metal-button').hide();

        //
        // initiate map depending on app mode
        // turn on layers, set start center and zoom
        // handle arsenic/lead toggle for orchard mode
        switch (APP.mode) {
            case 'tacoma':
                APP.smelterService.findSublayerById(APP.layerIds.plume).legendEnabled = true;
                //APP.smelterService.findSublayerById(APP.layerIds.orchards).renderer = renderer;
                start.zoom = 11;
                start.center = {
                    lon: -122.5,
                    lat: 47.27384
                };
                APP.view.constraints.maxZoom = 22
                break;
            case 'orchard': {
                ['orchards', 'sampledOrchardProperties', 'centralSamplesArsenic'].forEach(function (name) {
                    APP.smelterService.findSublayerById(APP.layerIds[name]).visible = true;
                });
                APP.smelterService.findSublayerById(APP.layerIds.plume).renderer = renderer;
                start.zoom = 7;
                start.center = {
                    lon: -120.317961,
                    lat: 47.125327
                };

                // get metals layers from map service
                let arsenic = APP.smelterService.findSublayerById(APP.layerIds.centralSamplesArsenic);
                let lead = APP.smelterService.findSublayerById(APP.layerIds.centralSamplesLead);

                // show metal layer toggle button if scale < minscale of arsenic layer
                APP.view.watch('scale', function (scale) {
                    if (scale <= arsenic.minScale) {
                        $('#metal-button').show();
                    } else {
                        $('#metal-button').hide();
                    }
                });

                // assign click function for metal toggle button
                $('#metal-button').click(function () {
                    arsenic.visible = !arsenic.visible;
                    lead.visible = !lead.visible;
                });

                // change button text depending on what layer is visible
                watchUtils.watch(arsenic, 'visible', function (visible) {
                    let text = visible ? 'Show Lead' : 'Show Arsenic';
                    $('#btn-change-metal').html(text);
                });

                break;
            }
            case 'everett':
                start.zoom = 14.5;
                start.center = {
                    lon: -122.193841,
                    lat: 48.009087
                };
                APP.view.constraints.maxZoom = 22
                break;
            case 'ucr':
                start.zoom = 11;
                start.center = {
                    lon: -117.789836,
                    lat: 48.910716
                };                
                break;
        }

        //
        // check URL search params for lat, lon, and zoom, set as start extent
        if (!searchparams.has('id') && searchparams.has('lat') && searchparams.has('lon') && searchparams.has('zoom')) {
            start.center = {
                lon: searchparams.get('lon'),
                lat: searchparams.get('lat')
            };
            start.zoom = searchparams.get('zoom');
        }

        //
        // create point from start object, used by view
        let point = new Point({
            latitude: start.center.lat,
            longitude: start.center.lon,
            spatialReference: {
                    wkid: 102100
                }
        });

        //
        // navigate to mode-specific start point
        APP.view.goTo({
            target: point,
            zoom: start.zoom
        });

        //
        // if query string has param ID, execute search for that EcologyIdentifier
        if (searchparams.has('id')) {
            APP.view.when(function () {
                APP.queryStringProperty(searchparams.get('id'));
            });
        }

        // if search in querystring, execute search at point passed in
        if (searchparams.has('search')) {

            APP.searchMethod = {
                'method': 'querystring',
                'location': point
            };

            APP.view.when(function () {
                APP.executeSearch(point);
                setQueryStringParam('search', 'true');

            });            
        }

        // define locator for search widget and reverse geocode in property search
        APP.locator = new Locator({
            url: "//geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer"
        });

        

        //---------------------------------------//
        // watching functions
        // change cursor to spinner if view is 
        // updating(layers loading etc)
        //---------------------------------------//

        //
        // function to update query string parameter
        function setQueryStringParam(param, value) {            
            let search = new URLSearchParams(window.location.search);
            search.set(param, value);
            window.history.replaceState(null, null, '?' + search.toString());
        }

        //
        // set location query string params on move
        watchUtils.whenTrue(APP.view, 'stationary', function () {
            if (APP.view.center) {
                setQueryStringParam('lat', Number.parseFloat(APP.view.center.latitude).toFixed(6));
                setQueryStringParam('lon', Number.parseFloat(APP.view.center.longitude).toFixed(6));
                setQueryStringParam('zoom', APP.view.zoom);
            }
        });

        //
        // complete loading bar when service finishes loading
        APP.view.whenLayerView(APP.smelterService)
            .then(function (l) {
                NProgress.done();
            });

        //
        // turn off imagery when zoomed out past a certain point
        watchUtils.whenFalse(APP.view, 'updating', function (f) {
            dom.byId("viewDiv").style.cursor = "auto";
        });

        //
        // get subunits graphics layer
        let subunitslayer = APP.map.findLayerById('subunitsGraphics');

        //
        // catch click event on view
        // if click isn't on subunits layer, execute search
        APP.view.on('click', function (evt) {
            if (evt.button === 0) { // only search if left click
                // detect if click is on subunit graphic
                APP.view.hitTest(evt).then(function (response) {
                    let subunits = response.results.filter(function (feat) {
                        return feat.graphic.layer === subunitslayer;
                    });

                    // only execute search if click isn't on subunit
                    if (subunits.length === 0) {
                        subunitslayer.removeAll();

                        // use in gtag
                        APP.searchMethod = {
                            'method': 'click',
                            'location': evt.mapPoint
                        };

                        APP.executeSearch(evt.mapPoint);
                    }
                });
            }
        });


        APP.view.when(function () {

            // show more info button
            $('#more-info').show();

            // Property status layer toggle button
            if (APP.test) {
                const statusLayer = APP.smelterService.findSublayerById(APP.layerIds.properties);
                $('#status-button-container').show();

                // toggle property status layer
                $('#status-button-container').click(function () {
                    statusLayer.visible = !statusLayer.visible;
                });
            }
        });

        //------------------------------------------------//
        // TODO: handle this better with list groups
        // assign click event to toggle sections in popup
        // once popup is rendered
        //------------------------------------------------//
        // toggle legend when header is clicked
        function toggleLegend(el) {
            $(el).find('.close').toggleClass('rotate');
            $('#legend-container').slideToggle(250);
        }

        $('#legend-header').click(function () {
            toggleLegend(this);
        });

        $('#legend-close-mobile').click(function () {
            toggleLegend(this);
        });

        // close modal button
        $('.close-modal').click(function () {
            $('.modal-overlay').hide();
            $('.custom-modal').hide();
        });

        // position of legend
        APP.view.watch('width', function (width) {
            if (width <= 600) {
                APP.view.ui.move('legend', 'top-right');
            } else {
                $('#legend').unbind();
                APP.view.ui.move('legend', 'bottom-right');
                if ($('#legend-container').is(':visible')) {
                    $('.close.hide-next.full').removeClass('rotate');
                } else {
                    $('.close.hide-next.full').addClass('rotate');
                }
            }
        });

        APP.view.when(function () {
            if (APP.view.width <= 600) {
                APP.view.ui.move('legend', 'top-right');
            }
            // show legend 
            $('.legend').show();
        });

        function legendClick() {
            // expand legend
            $('#legend').unbind();
            $('#legend').click(function () {
                if ($('#legend-container').is(':visible')) {
                    $('#legend-container').css('display', 'none');
                } else {
                    $('#legend-container').css('display', 'initial');
                }
            });
        }
        
        //-----------------------------------------//
        // set up widgets and view.ui
        //-----------------------------------------//

        // address finder
        let search = new Search({
            view: APP.view,
            popupEnabled: false,
            popupOpenOnSelect: false,
            resultGraphicEnabled: false,
            includeDefaultSources: false,
            sources: [
                {
                    locator: APP.locator,// defined earlier, used for reverse geocode as well
                    searchExtent: new Extent({
                        xmax: -12616814.790795209,
                        xmin: -14179799.145170076,
                        ymax: 6600676.1757940585,
                        ymin: 5475523.119436563,
                        spatialReference: {
                            wkid: 102100
                        }
                    }),
                    localSearchOptions: {
                        minScale: 50000,
                        distance: 10
                    },
                    singleLineFieldName: "SingleLine",
                    name: "Search for location",
                    placeholder: "Find address or place",
                    maxResults: 3,
                    suggestionsEnabled: true,
                    minSuggestCharacters: 2
                }
            ]
        });
        APP.view.ui.add(search, 'top-left');

        //
        // assign executeSearch() function to finding of a result
        search.on('select-result', function (evt) {
            
            // use in gtag
            APP.searchMethod = {
                'method': 'address',
                'location': evt.result.extent.center
            };

            APP.executeSearch(evt.result.extent.center);
        });


        APP.view.when(function () {
            document.querySelector('.esri-search__input').onfocusout = null;
        });            

        //
        // uses 'my location' if enabled on mobile and desktop
        var locate = new Locate({
            view: APP.view,
            graphic: APP.pointGraphic
        });

        // attach executeSearch() function to finding of a result
        locate.on("locate", function (event) {
            let locatePoint = new Point({
                'latitude': event.position.coords.latitude,
                'longitude': event.position.coords.longitude
            });

            // use in gtag
            APP.searchMethod = {
                'method': 'locateButton',
                'location': 'lat: ' + event.position.coords.latitude + '| lon: ' + event.position.coords.longitude
            };

            APP.executeSearch(locatePoint);            
        });

        // basemap toggle
        //let basemapToggle = new BasemapToggle({
        //    view: APP.view,
        //    nextBasemap: "hybrid"
        //});

        // More Information button in UI. Toggles modal
        APP.view.ui.add('more-info', 'top-right');
        APP.view.ui.add('subunit-popup', 'manual');

        // add legend widget and button when collapsed
        APP.view.ui.add('legend', 'bottom-right');
        APP.legend = new Legend({
            view: APP.view,
            container: 'legend-container',
            title: null
        });

        // zoom in/out button
        let zoom = new Zoom({
            view: APP.view
        });

        // arrange buttons
        APP.view.ui.move('zoom', 'top-left');
        APP.view.ui.add(locate, "top-left");


        // add property status layer if on test
        if (APP.test) {
            APP.view.ui.add('status-button-container', 'top-left');
        }

        //-----------------------------------------//
        // general app click events and functions
        //-----------------------------------------//

        bindListGroupListener();

        //
        // show info modal
        function showInfo() {
            $('#infoModal').show();
            $('.modal-overlay').show();
        }

        // open info modal
        $('#more-info').click(function () {
            showInfo();
        });

        $('.modal-overlay').click(function () {
            $('.custom-modal').hide();
            $('.modal-overlay').hide();
        });

        // show discalimer if cookie doesn't exist
        function showDisclaimer() {
            $('#disclaimerModal').show();
            $('.modal-overlay').show();
        }

        // open modal, expand and scroll to action levels section
        APP.openModalActionLevels = function () {
            let content = $('#modal-action-levels').next();
            content.prev().addClass('expanded');

            // open section
            content.show();

            // open modal
            showInfo();

            // hide other sections
            content.siblings('.content').hide();
            content.siblings().removeClass('expanded');
            document.getElementById('modal-action-levels').scrollIntoView();
        };

        // reload app on home click
        $('#home').click(function () {
            window.location.href = window.location.href;
        });

        // reload app on title click
        $('.header-title').click(function () {
            window.location.href = window.location.href;
        });

        // healthy actions tab clicked        
        $('#healthyActions').click(function () {
            window.open('https://ecology.wa.gov/Spills-Cleanup/Contamination-cleanup/Dirt-Alert-program/Healthy-actions', '_blank');
        });

        // add date to bottom of info modal
        $('.last-update').html('Last Updated ' + APP.buildDate);

        //-----------------------------------------//
        // general utility functions
        //-----------------------------------------//

        // handle cookie
        function createCookie(name, value, days) {
            var expires;
            if (days) {
                var date = new Date();
                date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
                expires = "; expires=" + date.toGMTString();
            }
            else expires = "";
            document.cookie = name + "=" + value + expires + "; samesite=strict; path=/";
        }

        function readCookie(name) {
            var nameEQ = name + "=";
            var ca = document.cookie.split(';');

            for (var i = 0; i < ca.length; i++) {
                var c = ca[i];
                while (c.charAt(0) === ' ') c = c.substring(1, c.length);
                if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
            }
            return null;
        }

        // show disclaimer modal if no cookie is found
        if (!readCookie('dirtalert')) {
            showDisclaimer();
            createCookie('dirtalert', 'true', 100);
        }

        //log error if view doesn't resolve
        function errback(error) {
            console.error('error: ', error);
        }
    });

function createElement(type, text, attributes) {
//function createElement(type, text = null, attributes = null) {

    let elem;
    // create element
    elem = document.createElement(type);

    // assign text
    if (text) {
        elem.textContent ? elem.textContent = text : elem.innerText = text;
    }

    // assign attributes
    if (attributes) {
        attributes.forEach(function (attr) {
            let key = Object.keys(attr)[0];
            elem.setAttribute(key, attr[key]);
        });
    }

    return elem;
}

function bindListGroupListener() {
    // add click listener to list group item action buttons
    $('.list-group-item-action').click(function () {

        // toggle expanded class for chevron rotation and active class
        $(this).toggleClass('expanded').toggleClass('active');

        // slidetoggle next content section
        let content = $(this).next();
        $(content).slideToggle(250).toggleClass('hidden');

        // hide other content sections
        let className = $(content).hasClass('sub-content') ? '.sub-content' : '.content';
        $(this).siblings(className).not(content).slideUp(250).addClass('hidden');

        // toggle active and expanded classes for other non-content sections
        $(this).siblings().not(className).removeClass('active').removeClass('expanded');
    });
};


require([
    'esri/tasks/IdentifyTask',
    'esri/tasks/support/IdentifyParameters',
    'esri/tasks/QueryTask',
    'esri/tasks/support/Query',
    'esri/geometry/Point',
    "esri/core/watchUtils",
    'dojo/domReady!'
],
    function (
        IdentifyTask,
        IdentifyParameters,
        QueryTask,
        Query,
        Point,
        watchUtils,
    ) {

        APP.queryStringProperty = function (ecyid) {
            
            // set up querytask
            propertyQueryTask = new QueryTask([APP.smelterService.url, APP.layerIds.properties].join('/'));

            // search for property in query string
            let propQuery = new Query({
                'where': "lower(EcologyIdentifier) like '%" + ecyid.toLowerCase() + "%'",
                'returnGeometry': true,
                'outFields': ['EcologyIdentifier'],
                'spatialRelationship': ''
            });
            APP.query = propQuery;

            watchUtils.whenFalseOnce(APP.view, 'updating', function (f) {

                propertyQueryTask.execute(propQuery)
                    .then(function (result) {

                        if (result.features.length >= 1) {

                            let centroid = new Point({
                                x: result.features[0].geometry.centroid.x,
                                y: result.features[0].geometry.centroid.y,
                                spatialReference: {
                                    wkid: 102100
                                }
                            });

                            if (result.features.length > 1) {
                                console.log(result.features.length + ' properties found; going to ' + result.features[0].attributes.EcologyIdentifier);
                            }

                            APP.searchMethod = {
                                'method': 'querystring',
                                'location': centroid
                            };

                            // execute search
                            APP.executeSearch(centroid);

                        } else {
                            alert('no property found');
                        }
                    });
            });
        };
    });;

require([
    'esri/Graphic',
    'esri/geometry/Point',
    'esri/tasks/support/Query',
    'esri/tasks/QueryTask',
    'esri/tasks/IdentifyTask',
    'esri/tasks/support/IdentifyParameters'
],
    function (
        Graphic,
        Point,
        Query,
        QueryTask,
        IdentifyTask,
        IdentifyParameters
    ) {

        //------------------------------------------------//
        // identify property at evt, return arsenic layer 
        // with deinition query applied point will have
        // property, contacts, and messages attached as 
        // attributes
        //------------------------------------------------//
        let searchCountGlobal = 0;
        APP.executeSearch = function (point) {

            // start progress bar
            NProgress.start();
            
            let popupContent = createElement('div', null, [{ id: 'popup-content'}]);
            popupContent.appendChild(createElement('div', null, [{ class: 'spinner-border' }, { id: 'content-spinner' }]));

            // property status
            popupContent.appendChild(createElement('div', null, [{ id: 'property-status' }, { class: 'popup-messages' }]));
            
            // documents
            popupContent.appendChild(createElement('div', null, [{ class: 'spinner-border' }, { role: 'status' }, { id: 'documents' }]));

            // messages
            popupContent.appendChild(createElement('div', null, [{ class: 'popup-messages hidden' }, { id: 'messages' }]));
            let listGroup = createElement('div', null, [{ class: 'list-group popup-content-lg hidden' }]);
            popupContent.appendChild(listGroup);

            // sampling results
            let title = createElement('button', null, [{ class: 'list-group-item list-group-item-action toggle hidden' }, { id: 'sampling' }]);
            listGroup.appendChild(title);
            title.appendChild(createElement('i', null, [{ class: 'fas marg fa-chevron-right' }]));
            title.appendChild(createElement('i', null, [{ class: 'fas marg fa-flask' }]));
            title.appendChild(createElement('span', 'Sampling Results'));
            let samplingContent = createElement('div', null, [{ class: 'list-group-item content hidden' }, { id: 'sampling-content' }]);
            listGroup.appendChild(samplingContent);
            let samplingContentLG = createElement('div', null, [{ class: 'list-group' }]);
            samplingContent.appendChild(samplingContentLG);

            ['arsenic', 'lead'].forEach(function (id) {
                samplingContentLG.appendChild(createElement('button', null, [{ class: 'list-group-item list-group-item-action sub-toggle' }, { id: id }]));
                samplingContentLG.appendChild(createElement('div', null, [{ class: 'list-group-item sub-content hidden' }, { id: id + '-content' }]));
            });

            // contacts
            listGroup.appendChild(createElement('button', null, [{ class: 'list-group-item list-group-item-action toggle hidden' }, { id: 'contacts' }]));
            listGroup.appendChild(createElement('div', null, [{ class: 'list-group-item content hidden' }, { id: 'contacts-content' }]));
            
            APP.view.popup.open({
                location: point,
                title: 'Searching for property',
                content: popupContent,
                actions: []
            });
            APP.view.popup.dockEnabled = true;
            APP.view.popup.dockOptions.position = 'bottom-left';            
            APP.view.popup.autoOpenEnabled = false;
            APP.view.popup.renderNow();

            // html observables for child list
            // get element
            const node = document.getElementsByClassName('esri-popup')[0];

            // configure 
            const config = {
                attributes: true,
                childList: true,
                subtree: true
            };

            // callback function 
            const callback = function (mutationList, observer) {
                mutationList.forEach(function (mutation) {
                    if (mutation.type === 'childList') {

                        //remove previously assigned events
                        $('.list-group-item-action').unbind();

                        bindListGroupListener();
                    }
                });
            };

            // set mutation observer on esri popup content
            let observer = new MutationObserver(callback);
            observer.observe(node, config);

            let search = {
                contacts: [],
                documents: [],
                ecyid: null,
                feature: null,
                graphic: null,
                hst: null,
                inSSP: false,
                inHST: false,
                inYard: false,
                inPlume: false,
                inOrchard: false,
                layers: [],
                open: null,
                point: point,
                plumeConcentration: null,
                propertyType: null,
                searchMethod: null,
                showPlume: true,
                subunits: [],
                zoom: 18
            };

            //
            // increment global count
            let searchCountLocal = ++searchCountGlobal;

            //
            // clear previous search graphics
            APP.view.graphics.removeAll();

            //
            // show loading image
            NProgress.start();

            //
            // set up identify parameters
            let ecologyIdentifierTask = new IdentifyTask(APP.smelterService.url);
            let params = new IdentifyParameters({
                returnGeometry: true,
                tolerance: 0,
                width: APP.view.width,
                height: APP.view.height,
                layerOption: 'all'
            });
            params.geometry = point;
            params.mapExtent = APP.view.extent;

            //
            // execute identify
            ecologyIdentifierTask.execute(params)
                .then(function (response) {
                    
                    // escape if counts don't match (another search has been fired)
                    if (searchCountGlobal !== searchCountLocal) {
                        return;
                    }

                    response.results.forEach(function (feat) {

                        switch (feat.layerId) {                            

                            case APP.layerIds.healthDept:
                                search.healthDept = feat.feature;
                                break;
                            case APP.layerIds.properties:
                                search.propertyType = 'tsp';
                                search.feature = feat.feature;
                                search.ecyid = feat.feature.attributes.EcologyIdentifier;

                                // get subunits, attach response to search object
                                getSubunits(search)
                                    .then(function (response) {
                                        response.features.length > 0 ? search.subunits = response.features : null;
                                    });

                                // if dev or ssp in ecyid, assign property type
                                ['dev', 'ssp'].forEach(function (type) {
                                    if (search.ecyid.toLowerCase().indexOf(type) > -1) {
                                        search.propertyType = type;
                                        search.zoom = 20;
                                    }
                                });

                                //// if dev or ssp in ecyid, assign property type
                                //['dev', 'ssp'].forEach(function (type) {
                                //    if (search.ecyid.toLowerCase().indexOf(type) > -1) {
                                //        search.propertyType = type === 'dev' ? 'vcp' : type;
                                //        search.zoom = 20;
                                //    }
                                //});
                                break;
                            case APP.layerIds.hstParcels:
                                if (search.propertyType !== 'ssp') {
                                    search.propertyType = 'hst';
                                    search.hst = true;
                                    // use hst id to apply def query
                                    APP.smelterService.findSublayerById(APP.layerIds.hstUnits).definitionExpression = 'ParcelID = ' + feat.feature.attributes.ParcelID;
                                }
                                break;
                            case APP.layerIds.rightsOfWay:
                                search.propertyType = 'row';
                                search.feature = feat.feature;
                                search.zoom = 20;
                                break;
                            case APP.layerIds.vcp:
                                search.propertyType = 'vcp';
                                search.feature = feat.feature;
                                break;
                            // get plume concentration
                            case APP.layerIds.plume:
                                search.plumeConcentration = feat.feature.attributes.NAME;
                                break;
                            case APP.layerIds.plumeBoundary:
                                search.inPlume = true;
                                break;
                            case APP.layerIds.sspBoundary:
                                search.inSSP = true;
                                search.inHST = true;
                                break;
                            case APP.layerIds.yardBoundary:
                                search.inYard = true;
                                break;
                            case APP.layerIds.everett:
                                search.propertyType = 'everett';
                                break;
                            case APP.layerIds.upperColumbia:
                                search.propertyType = 'ucr';
                                break;
                            case APP.layerIds.sampledOrchardProperties:
                                search.propertyType = APP.mode === 'orchard' ? 'sampledOrchardProperties': 'generalOrchard'; // only apply that property type if app is in orchard mode
                                break;
                            case APP.layerIds.orchards:
                                search.propertyType = APP.mode === 'orchard' ? 'orchard' : 'generalOrchard'; // only apply that property type if app is in orchard mode
                                break;
                            case APP.layerIds.orchardLands:
                                search.propertyType = 'generalOrchard';
                                break;
                        }
                    
                    });

                    let urlsearch = new URLSearchParams(window.location.search);
                    

                    //
                    // if property isn't null, populate query string with ecyid
                    if (search.ecyid !== null) {
                        // set url search parameters
                        urlsearch.set('id', search.ecyid);
                        window.history.replaceState(null, null, '?' + urlsearch.toString());
                    } else {
                        // clear url search parameters
                        urlsearch.delete('id');
                        window.history.replaceState(null, null, '?' + urlsearch.toString());
                    }

                    //
                    // assign graphic. polygon if feature !== null, else point
                    if (search.feature === null) {
                        search.graphic = new Graphic({
                            geometry: new Point({
                                'latitude': point.latitude,
                                'longitude': point.longitude
                            }),
                            symbol: {
                                type: "simple-marker",
                                style: "diamond",
                                outline: { width: 1 },
                                size: 16,
                                color: [255, 255, 0, 1]
                            }
                        });
                    } else {
                        search.graphic = new Graphic({
                            geometry: search.feature.geometry,
                            symbol: {
                                type: "simple-fill",
                                style: 'none',
                                outline: {
                                    color: [28, 251, 240],
                                    width: 4
                                }
                            }
                        });
                    }
                    APP.view.graphics.add(search.graphic);

                    //
                    // move map to search point/feature outline
                    if (search.feature === null) {
                        APP.view.goTo({
                            target: point,
                            zoom: search.zoom
                        });
                    } else {
                        APP.view.goTo({
                            target: search.feature.geometry.extent.expand(2)
                        });
                    }


                    //
                    // execute search promise chain
                    getExcavation(search.ecyid)
                        .then(function (response) {
                            search.excavation = response.features.length > 0 ? true : false;
                            return search;
                        })
                        .then(getAddress)
                        .then(function (response) {
                            search.address = response.attributes.Address === '' ? 'Property: No Address' : 'Property: ' + response.attributes.Address;
                            APP.view.popup.title = search.address;
                            APP.view.popup.open();
                            return search;
                        })
                        .then(formatMapService)
                        .then(formatPopup)
                        .then(getDocuments);
                });

            // fire GA event
            let label = JSON.stringify({ 'lat': APP.searchMethod.location.latitude, 'lon': APP.searchMethod.location.longitude });
            gtag('event', APP.searchMethod.method, {
                event_category: 'Dirt Alert Search',
                event_label: label
            });
        };

        //
        // get excavation based on ecologyidentifier
        function getExcavation(ecyid) {

            let excavationQueryTask = new QueryTask([APP.smelterService.url, APP.layerIds.excavation].join('/'));

            let excavationQuery = new Query({
                'where': "EcologyIdentifier = '" + ecyid + "'",
                'returnGeometry': false,
                'outFields': ['depth']
            });
            return excavationQueryTask.execute(excavationQuery);
        }

        //
        // get subunits for ecologyidentifier
        function getSubunits(search) {
            // disregard subunits if vcp property
            let where = search.propertyType !== 'vcp' ? "EcologyIdentifier = '" + search.ecyid + "'" : '1=0';
            
            let subunitsQueryTask = new QueryTask([APP.smelterService.url, APP.layerIds.subunitsArsenic].join('/'));

            let query = new Query({
                'where': where,
                //'returnGeometry': false,
                'returnGeometry': true,
                'outFields': ['*'],
                'spatialRelationship': ''
            });
            return subunitsQueryTask.execute(query);
        }

        //
        // get address of search point from location service.
        // display in popup if not an AREIS property
        function getAddress(search) {
            return APP.locator.locationToAddress({ location: search.point });
        }

    });

;
function formatPopup(search) {
    let msgArray = [];
    let removeSubunits = true;

    // orchard lands
    if (['orchard', 'sampledOrchardProperties'].indexOf(search.propertyType) > -1 && APP.mode === 'orchard') {
        
        if (search.propertyType === 'sampledOrchardProperties') {
            removeSubunits = false;
            require([
                'esri/Graphic',
                'esri/tasks/QueryTask',
                'esri/tasks/support/Query',
                'dojo/domReady!'
            ],
                function (
                    Graphic,
                    QueryTask,
                    Query,
                    dom
                ) {

                    let sampledPropertyQT = new QueryTask([APP.smelterService.url, APP.layerIds.sampledOrchardProperties].join('/'));

                    let sampleQuery = new Query({
                        where: '1=1',
                        returnGeometry: true,
                        outFields: ['*'],
                        geometry: search.point,
                        spatialRelationship: 'intersects'
                    });
                    sampledPropertyQT.execute(sampleQuery)
                        .then(function (response) {
                            if (response.features.length > 0) {

                                let geo = response.features[0].geometry;

                                // add graphic
                                let graphic = new Graphic({
                                    geometry: geo,
                                    symbol: {
                                        type: "simple-fill",
                                        style: 'none',
                                        outline: {
                                            color: [28, 251, 240],
                                            width: 4
                                        }
                                    }
                                });
                                APP.view.graphics.add(graphic);

                                // get samples
                                let centralSamplesLayerId = APP.smelterService.findSublayerById(APP.layerIds.centralSamplesArsenic).sublayers.items[0].id; // this is ridiculous
                                let qt = new QueryTask([APP.smelterService.url, centralSamplesLayerId].join('/'));

                                let query = new Query({
                                    where: '1=1',
                                    returnGeometry: true,
                                    outFields: ['*'],
                                    geometry: geo,
                                    spatialRelationship: 'contains'
                                });

                                qt.execute(query)
                                    .then(function (results) {
                                        if (results.features.length > 0) {
                                            
                                            // sampling results list group item title
                                            $('#sampling').removeClass('hidden');

                                            ['Arsenic', 'Lead'].forEach(function (metal) {
                                                let id = metal.toLowerCase();
                                                
                                                // list group item title
                                                let title = document.getElementById(id);

                                                // icon
                                                title.appendChild(createElement('i', null, [{ class: 'fas marg fa-chevron-right' }]));

                                                // text                    
                                                title.appendChild(createElement('span', metal + ' Results'));

                                                // list group item content
                                                let content = document.getElementById(id + '-content');
                                                
                                                // add text description
                                                content.appendChild(createElement('div', metal + ' XRF data in parts per million (ppm)', [{ class: 'first-row' }]));

                                                // add each subunit
                                                let sampleCount = 0;
                                                results.features.forEach(function (subunit) {
                                                    sampleCount++;

                                                    //// set text for element
                                                    let val = subunit.attributes[metal + '_ppm'];
                                                    if (val !== null) {
                                                        let valText = Number.parseFloat(val).toFixed(1) + ' ppm';
                                                        let s = 'Sample ' + sampleCount + ': ' + valText;

                                                        // create HTML
                                                        let row = createElement('div');
                                                        let span = createElement('span', s);
                                                        row.appendChild(span);

                                                        // add row to content div
                                                        content.appendChild(row);
                                                    }
                                                    
                                                });

                                                // toggle lead/arsenic layer when layer list group item is clicked
                                                let el = document.getElementById(id);
                                                el.addEventListener('click', function () {
                                                    APP.smelterService.findSublayerById(APP.layerIds['centralSamples' + metal]).visible = true;

                                                    ['Arsenic', 'Lead'].forEach(function (met) {
                                                        if (met !== metal) {
                                                            APP.smelterService.findSublayerById(APP.layerIds['centralSamples' + met]).visible = false;
                                                        }
                                                    });
                                                });
                                                
                                            });
                                        }
                                    });
                            }                            
                        });
                    

                });

            let d = createElement('div');
            let elems = [
                createElement('span', 'This property has been sampled, see results below.')
            ];

            elems.forEach(function (el) {
                d.appendChild(el);
            });

            msgArray.push(d);


        } else {
            let d = createElement('div');
            let elems = [
                createElement('span', 'This property is located within the footprint of a former orchard that was active during the era when lead arsenate was used as a pesticide. There is a high probability this location has elevated concentrations of lead and arsenic.'),
                createElement('br'),
                createElement('br'),
                createElement('span', 'The property owner may contact Ecology (contact info below) for sampling at no cost.  Sampling, and mitigation if necessary, will be required if this property is converted from agricultural use to residential, recreational or commercial use.')
            ];

            elems.forEach(function (el) {
                d.appendChild(el);
            });

            msgArray.push(d);
        }

        search.contacts.push(APP.contacts.orchard);

        search.propertyType = null;


    // TSP, Everett, or UCR, or anything
    } else {
        
        //
        // populate this info from health dept layer
        // add health department to contacts        
        if (search.healthDept !== undefined) {

            let healthDept = search.healthDept.attributes; // this assumes it's only valid for there to be one at a time
            let healthContact = {
                message: 'Contact Your Local Health Department',
                name: healthDept.name,
                title: null,
                phone: healthDept.phone,
                email: healthDept.email,
                open: false,
                url: null
            };

            switch (healthDept.name) {
                case 'Tacoma-Pierce County Health Department':
                    healthContact.url = APP.urls.pierceMainUrl;
                    search.healthDept.attributes.accessAgreement = APP.urls.pierceAccessAgreement;
                    break;
                case 'Public Health Seattle King County':
                    healthContact.url = APP.urls.kingMainUrl;
                    search.healthDept.attributes.accessAgreement = APP.urls.kingHstAccessAgreement;
                    break;
                case 'Thurston':
                    healthContact.url = 'https://www.co.thurston.wa.us/health/ehtsp/';
                    healthContact.name = 'Thurston County Health Department';
                    break;
                default:
                    search.healthDept.attributes.accessAgreement = '';
                    healthContact.url = '';
                    break;
            }

            search.contacts.push(healthContact);
        }
        else {
            APP.contacts.healthDept = null;
        }
        
        //
        // compile messages        
        
        //
        // in smelter plume
        if (search.inPlume) {

            // showing general contact info if no other contacts have been added to array
            if (search.contacts.length === 0) {
                APP.contacts.general.message = 'General Ecology Questions'; //TODO
                search.contacts.push(APP.contacts.general);
            }

            //
            // add eva to contacts (first if dev prop)
            if (['vcp', 'dev'].indexOf(search.propertyType) > -1 ) {
                search.contacts.unshift(APP.contacts.dev);
            } else {
                search.contacts.push(APP.contacts.dev);
            }
            
            //
            // in ssp
            if (search.inYard) {
                // add yard contact to contacts array
                search.contacts.push(APP.contacts.yard);

                // if in king county, swap access agreement to yard program version
                if (search.healthDept !== null && search.healthDept.attributes.name === 'Public Health Seattle King County') {
                    search.healthDept.attributes.accessAgreement = APP.urls.kingYardAccessAgreement;
                }
            } else if (search.inSSP && search.plumeConcentration !== null) {
                
                // offer home soil testing if not already sampled property
                if (['ssp', 'vcp', 'hst', 'dev'].indexOf(search.propertyType) < 0) {

                    if (search.healthDept !== null) {
                        
                        // only show access agreement if in King County, not Pierce
                        if (search.inHST) {

                            if (search.healthDept.attributes.name === "Public Health Seattle King County") {
                                let d = createElement('div');
                                d.appendChild(createElement('span', 'Interested in soil sampling through the Home Soil Testing Program? Fill out the'))
                                d.appendChild(createElement('a', ' access agreement ', [{ 'target': '_blank' }, { 'href': search.healthDept.attributes.accessAgreement }]));
                                d.appendChild(createElement('span', 'and contact your'));
                                d.appendChild(createElement('a', ' local health department ', [{ 'target': '_blank' }, { 'href': search.healthDept.attributes.url }]));
                                d.appendChild(createElement('span', 'to sign up.'));
                                msgArray.push(d);
                            } else {
                                let d = createElement('div');
                                d.appendChild(createElement('span', 'Interested in soil sampling through the Home Soil Testing Program? Contact your'));
                                d.appendChild(createElement('a', ' local health department ', [{ 'target': '_blank' }, { 'href': search.healthDept.attributes.url }]));
                                d.appendChild(createElement('span', 'to sign up.'));
                                msgArray.push(d);
                            }
                        }
                    }
                } else if (search.propertyType === 'hst') { // home soil testing parcel returned        
                    if (search.propertyType === 'hst') {

                        search.open = 'contacts';

                        let d = createElement('div');
                        let s1 = createElement('span', 'This property received soil sampling through the Home Soil Testing Program. To see your soil sampling results contact your ');
                        let a1 = createElement('a', 'local health department.', [{ 'target': '_blank' }, { 'href': search.healthDept.attributes.url }]);

                        // add to msg div
                        [s1, a1].forEach(function (el) {
                            d.appendChild(el);
                        });

                        // add to msg array
                        msgArray.push(d);
                    }

                }
            }

            //
            // childcare message added 07/25/2023            
            let childcareMsg = 'Attention Childcare Providers: Your property is located outside the Soil Safety Program service area. Ecology does not need to sample your property as part of your licensing process. Take a screenshot of this message and share with your licensing agent.';            
            if (search.inSSP) {                
                childcareMsg = 'Attention Childcare Providers: Your property is located within the Soil Safety Program service area. DCYF requires you to sign up for soil evaluation as part of your licensing process. Please use the contact information below to request further assistance.';
            }

            // add to msg div
            let d = createElement('div');
            s = createElement('span', childcareMsg);
            d.appendChild(s);
            // add to msg array
            msgArray.push(d);

            //
            // subunits exist
            if (search.subunits.length > 0 && search.propertyType !== 'ssp') {
                
                // property has excavation
                if (search.excavation) {

                    let d = createElement('div');
                    let s1 = createElement('span', 'This property received ');
                    let a1 = createElement('a', 'soil replacement', [{ 'target': '_blank' }, { 'href': APP.urls.soilReplacement }]);
                    let s2 = createElement('span', ' through the Department of Ecology. Some areas of soil contamination may remain. To see sampling and soil replacement records click on the links above.');

                    // add to msg div
                    [s1, a1, s2].forEach(function (el) {
                        d.appendChild(el);
                    });

                    // add to msg array
                    msgArray.push(d);

                    // status = 'Qualifies For Ecology Soil Replacement'
                } else if (search.ecyid !== null && search.feature.attributes.CleanupStatus === 'Qualifies For Ecology Soil Replacement') {

                    let d = createElement('div');
                    let s1 = createElement('span', 'This property may qualify for ');
                    let a1 = createElement('a', 'free soil replacement', [{ 'target': '_blank' }, { 'href': APP.urls.soilReplacement }]);
                    let s2 = createElement('span', ' through Ecology’s ');
                    let a2 = createElement('a', 'Yard Program', [{ 'target': '_blank' }, { 'href': APP.urls.yardProgram }]);
                    let s3 = createElement('span', '. Questions? See Contacts.');

                    // add to msg div
                    [s1, a1, s2, a2, s3].forEach(function (el) {
                        d.appendChild(el);
                    });

                    // add to msg array
                    msgArray.push(d);

                    // status = 'Action Complete (EPA)'
                } else if (search.feature.attributes.CleanupStatus === 'Action Complete (EPA)') {

                    let d = createElement('div');
                    let s1 = createElement('span', 'This property received soil replacement by Asarco overseen by the EPA. To see sampling and soil replacement records click on the links above. To learn how properties qualify go to ');
                    let a1 = createElement('a', 'Information', [{ 'target': '_blank' }, { 'href': "" }, { id: 'goToMoreInfo' }]);
                    let s2 = createElement('span', ' or see our ');
                    let a2 = createElement('a', 'website.', [{ 'target': '_blank' }, { 'href': APP.urls.yardProgram }]);

                    // add to msg div
                    [s1, a1, s2, a2].forEach(function (el) {
                        d.appendChild(el);
                    });

                    msgArray.push(d);

                } else if (search.feature.attributes.CleanupStatus === 'Does Not Qualify For Ecology Soil Replacement') {
                    let d = createElement('div');
                    let s1 = createElement('span', 'This property has been sampled. To see sampling records open Sampling Results below or click on the links above.');

                    // add to msg div
                    d.appendChild(s1);

                    msgArray.push(d);
                }
                
            } else if (search.propertyType === 'row') {

                let d = createElement('div');
                let s = createElement('span', 'This is a Right of Way. To see sampling records for the Right of Way, click on the links above.');

                // add to msg div
                d.appendChild(s);

                // add to msg array
                msgArray.push(d);

            } else if (search.propertyType === 'vcp') {

                let d = createElement('div');
                let s = createElement('span', 'Test your soil and complete cleanup during development or a landscaping project. Find out about soil sampling and cleanup on your property by going to Contacts and contacting Ecology.');

                // add to msg div
                d.appendChild(s);

                // add to msg array
                msgArray.push(d);
            } else if (search.inYard && ['hst', 'ssp'].indexOf(search.propertyType) < 0) {

                let d = createElement('div');
                let s1 = createElement('span', 'Are you a new homeowner? Interested in soil sampling? You can sign up for free soil sampling ');
                let a1 = createElement('a', 'here.', [{ 'target': '_blank' }, { 'href': search.healthDept.attributes.accessAgreement }]);

                // add to msg div
                [s1, a1].forEach(function (el) {
                    d.appendChild(el);
                });

                // add to msg array
                msgArray.push(d);
            }

            let firstMsg;
            if (['Limited Data', 'Military Base/State Facility', 'Under 20 ppm'].indexOf(search.plumeConcentration) > -1) {
                firstMsg = createElement('div');
                let s1 = createElement('span', 'Your property is located within the Tacoma Smelter Plume. Arsenic and lead are predicted to be below the state cleanup levels. You can take simple ');
                let a1 = createElement('a', 'Healthy Actions', [{ 'target': '_blank' }, { 'href': APP.urls.healthyActions }]);
                let s2 = createElement('span', ' to reduce you and your family’s exposure to soil contamination.');

                // add to msg div
                [s1, a1, s2].forEach(function (el) {
                    firstMsg.appendChild(el);
                });

            } else {
                firstMsg = createElement('div');
                let s1 = createElement('span', 'Your property is located within the Tacoma Smelter Plume. You can take simple ');
                let a1 = createElement('a', 'Healthy Actions', [{ 'target': '_blank' }, { 'href': APP.urls.healthyActions }]);
                let s2 = createElement('span', ' to reduce you and your family’s exposure to soil contamination.');

                // add to msg div
                [s1, a1, s2].forEach(function (el) {
                    firstMsg.appendChild(el);
                });
            }
            msgArray.unshift(firstMsg);

            //
            // Not in TSP Plume        
        } else {
            if (search.propertyType === 'everett') {

                // Property in Everett
                search.contacts.push(APP.contacts.everett);
                search.open = 'documents';
                search.showPlume = false;

                let d = createElement('div');
                let s1 = createElement('span', 'Your property is located within the ');
                let a1 = createElement('a', 'Everett Smelter Plume', [{ 'target': '_blank' }, { 'href': APP.urls.everett }]);
                let s2 = createElement('span', '. To see sampling and final cleanup records see linked documents above. If document links do not appear above, there are no Documents available for your property.');

                // add to msg div
                [s1, a1, s2].forEach(function (el) {
                    d.appendChild(el);
                });

                // empty array except for this message
                msgArray = [d];

                // Property in orchard lands
            } else if (search.propertyType === 'generalOrchard') {

                search.contacts.push(APP.contacts.orchard);
                search.showPlume = false;

                let d = createElement('div');

                let elems = [
                    createElement('span', 'This property is not located on ground that was occupied by an orchard during the era when lead arsenate was used as a pesticide.  As a result it is not likely to have elevated levels of lead or arsenic unless soil was imported from another location.  The property owner can still have Ecology sample at no cost to confirm.')
                ];

                // add to msg div
                elems.forEach(function (el) {
                    d.appendChild(el);
                });

                msgArray = [d];

                // Property in upper columbia shape
            } else if (search.propertyType === 'ucr') {
                search.open = 'contacts';
                search.contacts.push(APP.contacts.ucr);
                search.showPlume = false;

                let d = createElement('div');
                let elems = [
                    createElement('span', 'Your property is located within the '),
                    createElement('a', 'Upper Columbia River Lake Roosevelt Cleanup Site', [{ 'target': '_blank' }, { 'href': APP.urls.upperColumbiaGSP }]),
                    createElement('span', ' and may have soil contamination related to the Teck Trail smelter in British Columbia, Canada, or the Le Roi smelter that was formerly in Northport, Washington.'),
                    createElement('br'),
                    createElement('br'),
                    createElement('span', 'Contact Ecology, or visit our '),
                    createElement('a', 'Dirt Alert Website', [{ 'target': '_blank' }, { 'href': APP.urls.healthyActions }]),
                    createElement('span', ' for healthy actions that can help you and your family reduce your exposure to arsenic and lead in soil. If your property has not been sampled by the U.S. Environmental Protection Agency, consider '),
                    createElement('a', 'sampling your own soil', [{ 'target': '_blank' }, { 'href': APP.urls.soilSampling }]),
                    createElement('span', ' to find out if it has lead and arsenic contamination.')
                ];

                elems.forEach(function (el) {
                    d.appendChild(el);
                });

                // empty array except for this message
                msgArray = [d];

                // search search intersects nothing
            } else {

                // add general messages for all three contacts; change messages to be generic
                let d = createElement('div');
                let elems = [
                    createElement('span', 'This property is outside of any of the Smelter Plumes in Washington State, but we still recommend healthy actions. Visit our '),
                    createElement('a', 'Dirt Alert website ', [{ 'target': '_blank' }, { 'href': APP.urls.healthyActions }]),
                    createElement('span', ' for simple actions that can help you and your family reduce your exposure to contaminated soil.')
                ];

                elems.forEach(function (el) {
                    d.appendChild(el);
                });

                msgArray = [d];

                search.contacts.push(APP.contacts.general);
                APP.contacts.everett.message = 'General Information - Everett Cleanup Site';
                search.contacts.push(APP.contacts.everett);
                APP.contacts.ucr.message = 'General Information - Upper Columbia River Lake Roosevelt Cleanup Site';
                search.contacts.push(APP.contacts.ucr);
            }
        }

        //
        // If vcp property, overwrite other messages
        if (search.propertyType === 'vcp') {

            let gspUrl = `https://apps.ecology.wa.gov/cleanupsearch/site/${search.feature.attributes.CleanupSiteId}`;

            let d = createElement('div');
            let elems = [
                createElement('span', "Your property is located within the Tacoma Smelter Plume. Your property is part of the Voluntary Cleanup Program. Find out about soil sampling and cleanup. Click on the links above or contact Ecology's Technical Assistance Coordinator."),
                createElement('span', ' See'),
                createElement('a', ' Cleanup Site Page', [{ 'target': '_blank' }, { 'href': gspUrl }]),
                createElement('span', ' for more information.')
            ];

            elems.forEach(function (el) {
                d.appendChild(el);
            });

            // reset message array to only have this message
            msgArray = [d];
        }

        // ssp property
        // can't rely on being inside plume or SSP boundary
        if (search.propertyType === 'ssp') {
            
            APP.contacts.ssp.open = true;
            // add amy
            search.contacts.unshift(APP.contacts.ssp);

            let d = createElement('div');
            let s = createElement('span', 'This property is a school, park, or camp. To see sampling and cleanup records, click on the links above. Questions? See Contacts.');

            // add to msg div
            d.appendChild(s);

            // add to msg array
            msgArray.push(d);

            // zero out subunit array and add message
            // indicating proerty had soil work done 
            if (search.feature.attributes.SspVisitComplete === '1') {

                // empty subunits array to remove from popup
                search.subunits = [];

            }

        } else if (search.inPlume) {
            search.contacts.push(APP.contacts.ssp);
        }

        //
        // format property status - first message
        if (search.propertyType === 'vcp' && search.feature.attributes.CleanupSiteStatus !== undefined) {
            search.status = 'Status: ' + search.feature.attributes.CleanupSiteStatus;
        } else if (search.ecyid !== null) {
            if (['Null', '', 'Unknown'].indexOf(search.feature.attributes.CleanupStatus) < 0) {
                search.status = 'Status: ' + search.feature.attributes.CleanupStatus;
            }
        }        
    }


    //------------------------------------------------------------------------------------------//
    // format popup
    //------------------------------------------------------------------------------------------//
    search.collapsed = APP.view.popup.collapsed;
    APP.view.popup.collapsed = false;
    APP.view.popup.renderNow();
    search.status ? document.getElementById('property-status').appendChild(createElement('span', search.status)) : document.getElementById('property-status').setAttribute('class', '');
    $('#property-status').removeClass('hidden');

    //
    // messages
    let messages = document.getElementById('messages');        
    let popupmessages = document.getElementsByClassName('popup-message');
    for (i = 0; i < popupmessages.length; i++) {
        popupmessages(i).remove();
    }
    msgArray.forEach(function (elem) {
        elem.setAttribute('class', 'popup-message');
        messages.appendChild(elem);
    });
    
    document.getElementById('content-spinner').remove();
    $('#messages').removeClass('hidden');
    $('.popup-content-lg').removeClass('hidden');

    let el = document.getElementById('goToMoreInfo');
    if (el !== null) {
        el.addEventListener('click', function (evt) {
            evt.preventDefault();
            APP.openModalActionLevels();
        });
    }
    

    //
    // Subunits
    if (search.subunits.length > 0) {
        
        // units to show
        showunits = [];

        // format subunit names
        search.subunits.forEach(function (unit) {

            // format unit name
            let name = unit.attributes.Name.toLowerCase();

            if (name.indexOf('drainfield') > -1) {
                unit.sortNum = 150;
            } else if (name.indexOf('e') > -1) {
                unit.sortNum = Number(name.replace('e', '')) + 50;
                showunits.push(unit);
            } else {
                unit.sortNum = Number(name.replace('y', ''));
                showunits.push(unit);
            }
        });

        // assign subunits to only those we want to display
        search.subunits = showunits;

        // order subunits by unit name
        search.subunits.sort(function (a, b) {
            return Number(a.sortNum) - Number(b.sortNum);
        });

        // sampling results list group item title
        $('#sampling').removeClass('hidden');

        ['Arsenic', 'Lead'].forEach(function (metal) {
            let id = metal.toLowerCase();

            // list group item title
            let title = document.getElementById(id);

            // icon
            title.appendChild(createElement('i', null, [{ class: 'fas marg fa-chevron-right' }]));

            // text                    
            title.appendChild(createElement('span', metal + ' Results'));


            // list group item content
            let content = document.getElementById(id + '-content');

            // add text description
            content.appendChild(createElement('div', metal + ' 0-6" in parts per million (ppm)', [{ class: 'first-row' }]));

            // add each subunit
            search.subunits.forEach(function (subunit) {

                // catch those with arsenic = 20 and lead = 250 => excavated
                if (subunit.attributes.currentArsenic_0to6avg === 20 && subunit.attributes.currentLead_0to6avg === 250) {
                    subunit.attributes.excavated = 1;
                }

                // set text for element
                let name = 'Sampling Area ' + subunit.attributes.Name;
                let conc = subunit.attributes.excavated === 1 ? 'New Soil' : subunit.attributes['current' + metal + '_0to6avg'] + ' ppm';
                let s = name + ': ' + conc;

                // create HTML
                let row = createElement('div');
                let span = createElement('span', s);
                row.appendChild(span);

                // add row to content div
                content.appendChild(row);
            });

            // add orange new soil text if excavated subunit detected
            if (search.subunits.filter(function (unit) { return unit.attributes.excavated === 1 }).length > 0) {
                let orange = createElement('div', null, [{ class: 'orange' }]);
                content.appendChild(orange);
                let note = createElement('i', null, [{ class: 'fas marg fa-info-circle' }]);
                orange.appendChild(note);

                let orangetext = metal === 'Lead' ? 'New soil is below 50 ppm' : 'New soil is below 20 ppm';
                let span = createElement('span', orangetext);
                orange.appendChild(span);
            }

            // toggle lead/arsenic layer when layer list group item is clicked
            let el = document.getElementById(id);
            el.addEventListener('click', function () {

                APP.smelterService.findSublayerById(APP.layerIds['subunits' + metal]).visible = true;
                ['Arsenic', 'Lead'].forEach(function (met) {
                    if (met !== metal) {
                        APP.smelterService.findSublayerById(APP.layerIds['subunits' + met]).visible = false;
                    }
                });
            });
        });
    } else if (removeSubunits) {

        let hide = true;

        // remove LGI title
        document.getElementById('arsenic').remove();

        // get LGI content, set class, set text content
        let content = document.getElementById('arsenic-content');

        if (search.propertyType === 'hst') {
            content.appendChild(createElement('div', 'Contact your local health department for soil sampling results.'));
            hide = false;
        } else if (search.feature !== null) {
            if (search.feature.attributes.SspVisitComplete === '1') {
                content.appendChild(createElement('div', 'This property completed work through the Soil Safety Program. Please see documents for further information.'));
                hide = false;
            }
        } else if (search.plumeConcentration !== null) {
            content.appendChild(createElement('div', 'Predicted Arsenic Concentration: ' + search.plumeConcentration + '.'));
            hide = false;
        }



        content.setAttribute('class', 'list-group-item');
        ['sampling'].forEach(function (id) {
            $('#' + id).removeClass('hidden');
        });

        // remove lead LGIs
        ['lead', 'lead-content'].forEach(function (id) {
            document.getElementById(id).remove();
        });

        if (hide) {
            ['sampling', 'sampling-content'].forEach(function (id) {
                document.getElementById(id).remove();
            });
        }               
    }

    //
    // Contacts
    if (search.contacts.length > 0) {

        //
        // Contact Title
        let contactTitle = document.getElementById('contacts');
        contactTitle.appendChild(createElement('i', null, [{ class: 'fas marg fa-chevron-right' }]));
        contactTitle.appendChild(createElement('i', null, [{ class: 'far marg fa-address-card' }]));
        contactTitle.appendChild(createElement('span', 'Contacts'));
        $('#contacts').removeClass('hidden');

        //
        // Contact Content
        let contactContent = document.getElementById('contacts-content');

        // create another list group for contacts
        let contactListGroup = createElement('div', null, [{ class: 'list-group' }]);
        contactContent.appendChild(contactListGroup);

        search.contacts.forEach(function (contact) {
            // title
            let lgi = createElement('button', null, [{ class: 'list-group-item list-group-item-action sub-toggle d-flex align-items-center' }]);
            lgi.appendChild(createElement('i', null, [{ class: 'fas marg fa-chevron-right' }]));
            lgi.appendChild(createElement('span', contact.message));
            contactListGroup.appendChild(lgi);

            // content
            let lgiContent = createElement('div', null, [{ class: 'list-group list-group-item sub-content hidden' }]);

            // contact name
            let dcontact = createElement('div', null, [{ class: 'contact-row' }]);
            lgiContent.appendChild(dcontact);
            dcontact.appendChild(createElement('i', null, [{ class: 'far marg fa-user' }]));


            let contactA = contact.name + (contact.title !== null ? ' (' + contact.title + ')' : '');
            dcontact.appendChild(createElement('a', contactA, [{ target: '_blank' }, { href: contact.url }]));

            // contact email
            let demail = createElement('div', null, [{ class: 'contact-row' }]);
            demail.appendChild(createElement('i', null, [{ class: 'far marg fa-envelope' }]));
            demail.appendChild(createElement('a', contact.email, [{ href: 'mailto:' + contact.email }]));

            // contact phone
            let dphone = createElement('div', null, [{ class: 'contact-row' }]);
            dphone.appendChild(createElement('i', null, [{ class: 'fas marg fa-phone-alt' }]));
            dphone.appendChild(createElement('a', contact.phone, [{ href: 'tel:' + contact.phone }]));

            // contact website
            let dwebsite = createElement('div', null, [{ class: 'contact-row' }]);
            dwebsite.appendChild(createElement('i', null, [{ class: 'fas marg fa-laptop-code' }]));
            dwebsite.appendChild(createElement('a', 'website', [{ target: '_blank' }, { href: contact.url }]));

            // append contact rows 
            [demail, dphone, dwebsite].forEach(function (elem) {
                lgiContent.appendChild(elem);

            });
            contactListGroup.appendChild(lgiContent);
        });
    }

    // clear property boundary/point graphics from map when popup is closed
    APP.view.popup.watch('visible', function (vis) {
        
        if (!vis) {
            // remove property graphic
            APP.view.graphics.removeAll();

            // remove subunit graphics
            let units = APP.map.findLayerById('subunitsGraphics');
            units.removeAll();

            // turn off subunit layers from service
            APP.smelterService.findSublayerById(APP.layerIds['subunitsArsenic']).visible = false;
            APP.smelterService.findSublayerById(APP.layerIds['subunitsLead']).visible = false;
            APP.smelterService.findSublayerById(APP.layerIds['subunitOutlines']).visible = false;
            APP.smelterService.findSublayerById(APP.layerIds['hstUnits']).visible = false;

            // remove id from url params
            let location = window.location;
            let url = new URL(location);
            let searchparams = new URLSearchParams(url.search);
            searchparams.delete('id');

            // replace url
            // not compatible with IE, which some people still use...
            //window.history.replaceState({}, '', `${location.pathname}?${searchparams}`);
            window.history.replaceState({}, '', location.pathname + '?' + searchparams);

            
        }
    });

    // complete progress bar
    NProgress.done();
    return search;
    
};

////-----------------------------//
//// change layer symbology and 
//// visibility 
////-----------------------------//
function formatMapService(search) {
    
    // if ssp or vcp, set point at which map switches to plume layer
    if (['ssp', 'vcp', 'dev'].indexOf(search.propertyType) > -1) {
        APP.propToPlumeScale = 20000;
    } else {
        APP.propToPlumeScale = 3000;
    }

    // find layers that need scale updating
    APP.map.findLayerById('mapservice').sublayers.items.forEach(function (layer) {
        if (layer.setMax) {            
            layer.maxScale = APP.propToPlumeScale;
        }
        if (layer.setMin) {
            layer.minScale = APP.propToPlumeScale;
        }
    });

    let layers = {
        plume: APP.smelterService.findSublayerById(APP.layerIds.plume),
        subunitsAs: APP.smelterService.findSublayerById(APP.layerIds.subunitsArsenic),
        subunitsPb: APP.smelterService.findSublayerById(APP.layerIds.subunitsLead),
        excavation: APP.smelterService.findSublayerById(APP.layerIds.excavation),
        subunitOutlines: APP.smelterService.findSublayerById(APP.layerIds.subunitOutlines),
        hst: APP.smelterService.findSublayerById(APP.layerIds.hstUnits),
        row: APP.smelterService.findSublayerById(APP.layerIds.rightsOfWay),
        vcp: APP.smelterService.findSublayerById(APP.layerIds.vcp)
    };

    // set visibility to false initially
    Object.keys(layers).forEach(function (layer) {
        layers[layer].visible = false;
    });

    // turn on plume unless search.showPlume set to false
    layers.plume.visible = true;
    !search.showPlume ? layers.plume.visible = false : null;

    // if property selected, set definition expresssion
    if (search.ecyid !== null) {

        if (search.propertyType === null) {
            search.zoom = null;
        }

        // definition expression
        let defexp = "EcologyIdentifier = '" + search.ecyid + "'";

        // apply definition expression to layer labelled as such in layers array up top
        APP.applyDefExpLayers.forEach(function (l) {
            APP.smelterService.findSublayerById(l.id).definitionExpression = defexp;
        });

        // turn on subunits layer with def exp applied
        
        // subunit graphic layer
        let units = APP.map.findLayerById('subunitsGraphics');
        units.removeAll();

        if (search.subunits.length > 0) {

            if (search.feature.attributes.SspVisitComplete === '0') {
                layers.subunitsAs.visible = true;
            }

            require([
                'esri/Graphic'
            ],
            function (
                Graphic,
            ) {
                // create highlight graphic without geometry
                let highlight = new Graphic({
                    symbol: {
                        type: 'simple-fill',
                        color: [0, 0, 0, 0],
                        outline: {
                            color: 'darkorange',
                            width: 3
                        }
                    }
                });
                APP.view.graphics.add(highlight);

                let graphics = [];
                search.subunits.forEach(function (unit) {

                    graphics.push(new Graphic({
                        geometry: unit.geometry,
                        attributes: unit.attributes,
                        symbol: {
                            type: 'simple-fill',
                            color: [0, 0, 0, 0],
                            outline: {
                                color: 'black',
                                width: 1
                            }
                        }                        
                    }));
                });

                // if popup closed set search = null
                $('.esri-icon-close').click(function () {
                    search = null;
                });

                // add graphics to layer
                units.addMany(graphics);

                //
                // remove previous click/move event handlers
                // 
                try {
                    APP.viewEventHandlers.forEach(function (h) {
                        h.remove();
                    })
                    APP.viewEventHandlers = [];
                } catch (error) {
                    APP.viewEventHandlers = [];
                }


                //
                // if SSP property and had completion visit, don't show subunit concentrations
                // as they are likely old and higher then existing values
                if (search.feature.attributes.SspVisitComplete !== '1') {
                    APP.viewEventHandlers = [
                        APP.view.on('pointer-move', eventHandler),
                        APP.view.on('pointer-down', eventHandler),
                        APP.view.on('immediate-click', eventHandler)
                    ];
                }

                function eventHandler(evt) {
                    APP.view.hitTest(evt).then(function (response) {

                        let graphics = response.results.filter(function (result) {
                            return result.graphic.layer === units;
                        });

                        if (graphics.length > 0) {

                            const g = graphics[0].graphic;

                            let y = '-' + (APP.view.height - evt.y);
                            let x = -1 * (APP.view.width / 2) + evt.x;

                            let content = '<div>Arsenic: ' + g.attributes.currentArsenic_0to6avg + ' ppm</div>';
                            content += '<div>Lead: ' + g.attributes.currentLead_0to6avg + ' ppm</div>';

                            $('#subunit-popup-title').html('Unit ' + g.attributes.Name);
                            $('#subunit-popup-content').html(content);
                            $('#subunit-popup').css('top', evt.y + 5);
                            $('#subunit-popup').css('left', evt.x + 5);
                            $('#subunit-popup').show();

                            prevGraphic = g;

                            highlight.geometry = g.geometry;

                        } else {
                            highlight.geometry = null;
                            $('#subunit-popup').fadeOut(150);
                        }
                    });
                }

            });
        
        } 
        // turn on excavation if that property has excavation
        search.excavation ? layers.excavation.visible = true : null;
    }

    // ROW visibility
    search.plumeConcentration !== null ? layers.row.visible = true : null;

    // VCP visibility
    search.propertyType === 'vcp' ? layers.vcp.visible = true : null;

    // home soil testing
    search.hst ? layers.hst.visible = true : null;

    return search;
};
//------------------------------------------------//
// get documents
//------------------------------------------------//

function getDocuments(search) {
    //
    // get documents from service
    if (search.propertyType !== null) {
        
        let appPath = window.location.origin + APP.AppBasepath;
        let searchUrl = appPath;

        if (search.feature !== null) {
            if (search.propertyType === 'vcp') {
                searchUrl += '/document/search?csid=' + search.feature.attributes.CleanupSiteId;
            } else {
                searchUrl += '/document/search?PropertyId=' + search.feature.attributes.EcologyIdentifier;
            }            
        } else {
            removeDocs();
            return search;
        }
        
        //
        // get documents
        $.get(searchUrl)
            .done(function (docs) {
                
                if (docs.length > 0) {
                    
                    let sortedDocs = [];
                    let ecyLetter = false;

                    docs.forEach(function (doc) {
                        switch (doc.Title) {
                            case 'Ecology Completion Letter':
                                sortedDocs.unshift(doc);
                                ecyLetter = true;
                                break;
                            case 'EPA Document':
                                if (ecyLetter) {
                                    sortedDocs = [sortedDocs[0]].concat([doc]).concat(sortedDocs.slice(1, sortedDocs.length));
                                } else {
                                    sortedDocs.unshift(doc);
                                }
                                break;
                            default:
                                sortedDocs.push(doc);
                                break;
                        }
                    });

                    search.documents = sortedDocs;
                    
                    APP.view.popup.collapsed = false;
                    APP.view.popup.renderNow();

                    // replace with doc list
                    let documents = document.getElementById('documents');
                    if (documents !== null) {
                        documents.setAttribute('class', 'list-group popup-messages');

                        sortedDocs.forEach(function (doc) {
                            //let lgi = createElement('div', null, [{ class: 'list-group-item' }]);
                            let lgi = createElement('div', null, [{ class: 'popup-document' }]);

                            lgi.appendChild(createElement('i', null, [{ class: 'far marg fa-file' }]));
                            let downloadUrl = appPath + '/document/download?did=' + doc.DocumentId;
                            lgi.appendChild(createElement('a', doc.Title, [{ href: downloadUrl }, { target: '_blank' }]));

                            documents.appendChild(lgi);
                        });
                    }

                    if (APP.view.width < 600) {
                        APP.view.popup.collapsed = true;
                        $('.esri-popup__content').show();
                    }

                } else {
                    removeDocs();
                }

            });
    } else {
        removeDocs();
    }

    function removeDocs() {
        
        // complete progress bar
        NProgress.done();

        APP.view.popup.renderNow();
        let docs = document.getElementById('documents');
        docs.remove();
    }

    return search;
};
