import { defineComponent, getCurrentInstance, createCommentVNode, ref, computed, watch, onUnmounted, h } from 'vue';
import { useCommon } from '../composables/index';
import { kebabCase } from '../utils/util';
import { clearColor, scissorRectangle } from '../utils/cesium-props';
import { useCommon as useCommon$1 } from '../composables';
import shaderSource from '../vc-shared/materials/shaders/RadarScan';
import shaderSource$1 from '../vc-shared/materials/shaders/CircleScan';
import { hSlot } from '../utils/private/render';

/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

function __awaiter(thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
}

const defaultProps = Object.assign(Object.assign(Object.assign({ fragmentShader: String, uniforms: Object, textureScale: {
        type: Number
    }, forcePowerOfTwo: {
        type: Boolean,
        default: false
    }, sampleMode: Number, pixelFormat: Number, pixelDatatype: Number }, clearColor), scissorRectangle), { name: String });

var VcPostProcessStage = defineComponent({
    name: 'VcPostProcessStage',
    props: defaultProps,
    emits: ['beforeLoad', 'ready', 'destroyed'],
    setup(props, ctx) {
        const instance = getCurrentInstance();
        instance.cesiumClass = 'PostProcessStage';
        instance.cesiumEvents = [];
        const commonState = useCommon(props, ctx, instance);
        if (commonState === void 0) {
            return;
        }
        const { $services } = commonState;
        instance.mount = () => __awaiter(this, void 0, void 0, function* () {
            const { postProcessStages } = $services;
            const stage = postProcessStages.add(instance.cesiumObject);
            return postProcessStages.contains(stage);
        });
        instance.unmount = () => __awaiter(this, void 0, void 0, function* () {
            const { postProcessStages } = $services;
            return postProcessStages === null || postProcessStages === void 0 ? void 0 : postProcessStages.remove(instance.cesiumObject);
        });
        return () => createCommentVNode(kebabCase(instance.proxy.$options.name));
    }
});

function useRadar ($services) {
    const webgl = options => {
        const { viewer } = $services;
        const cartographicCenter = Cesium.Cartographic.fromCartesian(options.position, viewer.scene.globe.ellipsoid);
        const _Cartesian3Center = Cesium.Cartographic.toCartesian(cartographicCenter, viewer.scene.globe.ellipsoid);
        const _Cartesian4Center = new Cesium.Cartesian4(_Cartesian3Center.x, _Cartesian3Center.y, _Cartesian3Center.z, 1);
        const _CartographicCenter1 = new Cesium.Cartographic(cartographicCenter.longitude, cartographicCenter.latitude, cartographicCenter.height + 500);
        const _Cartesian3Center1 = Cesium.Cartographic.toCartesian(_CartographicCenter1, viewer.scene.globe.ellipsoid);
        const _Cartesian4Center1 = new Cesium.Cartesian4(_Cartesian3Center1.x, _Cartesian3Center1.y, _Cartesian3Center1.z, 1);
        const _CartographicCenter2 = new Cesium.Cartographic(cartographicCenter.longitude + Cesium.Math.toRadians(0.001), cartographicCenter.latitude, cartographicCenter.height);
        const _Cartesian3Center2 = Cesium.Cartographic.toCartesian(_CartographicCenter2, viewer.scene.globe.ellipsoid);
        const _Cartesian4Center2 = new Cesium.Cartesian4(_Cartesian3Center2.x, _Cartesian3Center2.y, _Cartesian3Center2.z, 1);
        const _RotateQ = new Cesium.Quaternion();
        const _RotateM = new Cesium.Matrix3();
        const _time = (new Date()).getTime();
        const _scratchCartesian4Center = new Cesium.Cartesian4();
        const _scratchCartesian4Center1 = new Cesium.Cartesian4();
        const _scratchCartesian4Center2 = new Cesium.Cartesian4();
        const _scratchCartesian3Normal = new Cesium.Cartesian3();
        const _scratchCartesian3Normal1 = new Cesium.Cartesian3();
        const uniforms = {
            u_scanCenterEC: function () {
                return Cesium.Matrix4.multiplyByVector(viewer.camera.viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
            },
            u_scanPlaneNormalEC: function () {
                const temp = Cesium.Matrix4.multiplyByVector(viewer.camera.viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
                const temp1 = Cesium.Matrix4.multiplyByVector(viewer.camera.viewMatrix, _Cartesian4Center1, _scratchCartesian4Center1);
                _scratchCartesian3Normal.x = temp1.x - temp.x;
                _scratchCartesian3Normal.y = temp1.y - temp.y;
                _scratchCartesian3Normal.z = temp1.z - temp.z;
                Cesium.Cartesian3.normalize(_scratchCartesian3Normal, _scratchCartesian3Normal);
                return _scratchCartesian3Normal;
            },
            u_radius: options.radius,
            u_scanLineNormalEC: function () {
                const temp = Cesium.Matrix4.multiplyByVector(viewer.camera.viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
                const temp1 = Cesium.Matrix4.multiplyByVector(viewer.camera.viewMatrix, _Cartesian4Center1, _scratchCartesian4Center1);
                const temp2 = Cesium.Matrix4.multiplyByVector(viewer.camera.viewMatrix, _Cartesian4Center2, _scratchCartesian4Center2);
                _scratchCartesian3Normal.x = temp1.x - temp.x;
                _scratchCartesian3Normal.y = temp1.y - temp.y;
                _scratchCartesian3Normal.z = temp1.z - temp.z;
                Cesium.Cartesian3.normalize(_scratchCartesian3Normal, _scratchCartesian3Normal);
                _scratchCartesian3Normal1.x = temp2.x - temp.x;
                _scratchCartesian3Normal1.y = temp2.y - temp.y;
                _scratchCartesian3Normal1.z = temp2.z - temp.z;
                const tempTime = (((new Date()).getTime() - _time) % options.interval) / options.interval;
                Cesium.Quaternion.fromAxisAngle(_scratchCartesian3Normal, tempTime * Cesium.Math.PI * 2, _RotateQ);
                Cesium.Matrix3.fromQuaternion(_RotateQ, _RotateM);
                Cesium.Matrix3.multiplyByVector(_RotateM, _scratchCartesian3Normal1, _scratchCartesian3Normal1);
                Cesium.Cartesian3.normalize(_scratchCartesian3Normal1, _scratchCartesian3Normal1);
                return _scratchCartesian3Normal1;
            },
            u_scanColor: options.color
        };
        return {
            shaderSource,
            uniforms
        };
    };
    return {
        webgl
    };
}

function useCircle ($services) {
    const webgl = options => {
        const { viewer } = $services;
        const cartographicCenter = Cesium.Cartographic.fromCartesian(options.position, viewer.scene.globe.ellipsoid);
        const _Cartesian3Center = Cesium.Cartographic.toCartesian(cartographicCenter, viewer.scene.globe.ellipsoid);
        const _Cartesian4Center = new Cesium.Cartesian4(_Cartesian3Center.x, _Cartesian3Center.y, _Cartesian3Center.z, 1);
        const _CartographicCenter1 = new Cesium.Cartographic(cartographicCenter.longitude, cartographicCenter.latitude, cartographicCenter.height + 500);
        const _Cartesian3Center1 = Cesium.Cartographic.toCartesian(_CartographicCenter1, viewer.scene.globe.ellipsoid);
        const _Cartesian4Center1 = new Cesium.Cartesian4(_Cartesian3Center1.x, _Cartesian3Center1.y, _Cartesian3Center1.z, 1);
        const _time = new Date().getTime();
        const _scratchCartesian4Center = new Cesium.Cartesian4();
        const _scratchCartesian4Center1 = new Cesium.Cartesian4();
        const _scratchCartesian3Normal = new Cesium.Cartesian3();
        const uniforms = {
            u_scanCenterEC: function () {
                return Cesium.Matrix4.multiplyByVector(viewer.camera.viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
            },
            u_scanPlaneNormalEC: function () {
                const temp = Cesium.Matrix4.multiplyByVector(viewer.camera.viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
                const temp1 = Cesium.Matrix4.multiplyByVector(viewer.camera.viewMatrix, _Cartesian4Center1, _scratchCartesian4Center1);
                _scratchCartesian3Normal.x = temp1.x - temp.x;
                _scratchCartesian3Normal.y = temp1.y - temp.y;
                _scratchCartesian3Normal.z = temp1.z - temp.z;
                Cesium.Cartesian3.normalize(_scratchCartesian3Normal, _scratchCartesian3Normal);
                return _scratchCartesian3Normal;
            },
            u_radius: function () {
                return (options.radius * ((new Date().getTime() - _time) % options.interval)) / options.interval;
            },
            u_scanColor: options.color
        };
        return {
            shaderSource: shaderSource$1,
            uniforms
        };
    };
    return {
        webgl
    };
}

const defaultOptions = {
    position: [0, 0],
    radius: 1500,
    interval: 3500,
    color: [0, 0, 0, 255]
};
var VcPostProcessStageScan = defineComponent({
    name: 'VcPostProcessStageScan',
    props: {
        type: {
            type: String,
            default: 'radar'
        },
        options: Object
    },
    setup(props, ctx) {
        const instance = getCurrentInstance();
        instance.cesiumClass = 'VcPostProcessStageScan';
        instance.cesiumEvents = [];
        const commonState = useCommon$1(props, ctx, instance);
        if (commonState === void 0) {
            return;
        }
        const fragmentShader = ref('');
        const uniforms = ref(null);
        const { $services } = commonState;
        const useRadarState = useRadar($services);
        const useCircleState = useCircle($services);
        let unwatchFns = [];
        const options = computed(() => {
            return Object.assign({}, defaultOptions, props.options);
        });
        unwatchFns.push(watch(() => options, val => {
            if (instance.mounted) {
                instance.proxy.reload();
            }
        }, { deep: true }));
        instance.createCesiumObject = () => __awaiter(this, void 0, void 0, function* () {
            const opts = commonState.transformProps(options.value);
            let result;
            if (props.type === 'radar') {
                result = useRadarState.webgl(opts);
            }
            else if (props.type === 'circle') {
                result = useCircleState.webgl(opts);
            }
            fragmentShader.value = result.shaderSource;
            uniforms.value = result.uniforms;
            return true;
        });
        onUnmounted(() => {
            unwatchFns.forEach(item => item());
            unwatchFns = [];
        });
        return () => {
            return h(VcPostProcessStage, {
                fragmentShader: fragmentShader.value,
                uniforms: uniforms.value
            });
        };
    }
});

var VcPostProcessStageCollection = defineComponent({
    name: 'VcPostProcessStageCollection',
    props: {
        postProcesses: {
            type: Array,
            default: () => []
        }
    },
    emits: ['beforeLoad', 'ready', 'destroyed'],
    setup(props, ctx) {
        const instance = getCurrentInstance();
        instance.cesiumClass = 'PostProcessStage';
        instance.cesiumEvents = [];
        const commonState = useCommon(props, ctx, instance);
        if (commonState === void 0) {
            return;
        }
        const { $services } = commonState;
        const stages = [];
        let unwatchFns = [];
        unwatchFns.push(watch(() => props.postProcesses, val => {
            if (instance.mounted) {
                instance.proxy.reload();
            }
        }, { deep: true }));
        instance.createCesiumObject = () => __awaiter(this, void 0, void 0, function* () {
            return stages;
        });
        instance.mount = () => __awaiter(this, void 0, void 0, function* () {
            const { postProcessStages } = $services;
            props.postProcesses.forEach(postProcess => {
                const opts = commonState.transformProps(postProcess);
                stages.push(postProcessStages.add(new Cesium.PostProcessStage(opts)));
            });
            return true;
        });
        instance.unmount = () => __awaiter(this, void 0, void 0, function* () {
            const { postProcessStages } = $services;
            stages.forEach(stage => {
                postProcessStages.remove(stage);
            });
            stages.length = 0;
            return true;
        });
        onUnmounted(() => {
            unwatchFns.forEach(item => item());
            unwatchFns = [];
        });
        return () => ctx.slots.default ? (h('i', {
            class: kebabCase(instance.proxy.$options.name),
            style: { display: 'none !important' }
        }, hSlot(ctx.slots.default))) : createCommentVNode(kebabCase(instance.proxy.$options.name));
    }
});

const components = [
    VcPostProcessStage,
    VcPostProcessStageScan,
    VcPostProcessStageCollection
];
const install = (app) => {
    components.forEach(cmp => {
        app.component(cmp.name, cmp);
    });
};
var index = {
    install
};

export default index;
export { VcPostProcessStage, VcPostProcessStageCollection, VcPostProcessStageScan };
