import React, { Component } from 'react';
import { StyleSheet, View, Dimensions, ActivityIndicator, StatusBar } from 'react-native';
import MapView, { Marker, Region } from 'react-native-maps';
import { connect } from 'redux-su';
import { NavigationActions } from 'react-navigation';

import MapOverlay from './MapOverlay';
import MapObjects from './MapObjects';
import PortalPanel from './PortalPanel';
import debounce, { getBottomSpace } from '../helper';
import actions from '../Actions/actions';
import { LatLng } from '../Api/interfaces';
import { getZoomByRegion, getDataZoomForMapZoom } from '../Api/api';

const { width, height } = Dimensions.get("screen")
const draggableRange = {
    top: height / 1.75,
    bottom: 120 + getBottomSpace()
}

type Props = any
type State = any
class Map extends Component<Props, State> {
    static navigationOptions = ({ navigation }) => {
        return {
            title: 'Карта',
        };
    };
    refreshTimer: number | undefined
    map!: MapView;
    constructor(props: Props) {
        super(props)
        this.state = {
            user: undefined,
            region: null,
            dataZoom: 15,
        }
        this.load = debounce(this.load, 300)
    }
    componentDidMount() {
        this.refreshTimer = setInterval(() => {
            this.refresh()
        }, 30000)
    }
    componentWillUnmount() {
        clearInterval(this.refreshTimer)
    }
    componentWillMount() {
        const setPosition = (position) => {
            this.setState({
                user: {
                    latitude: position.coords.latitude,
                    longitude: position.coords.longitude
                },
            });
        }
        navigator.geolocation.getCurrentPosition(
            setPosition,
            error => alert(error.message),
            { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
        );
        navigator.geolocation.watchPosition(
            setPosition,
            error => alert(error.message),
            { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
        )
    }
    onRegionChange = (region: Region) => {
        const zoom = getZoomByRegion(width, region)
        const dataZoom = getDataZoomForMapZoom(zoom);
        this.setState({ region, dataZoom })
        this.props.actions.setRegion(region)
        setImmediate(() => this.load(false))
    }

    refresh = () => {
        setImmediate(() => this.load(true))
    }

    load = async (refresh: boolean) => {
        if (this.state.region != null) {
            this.props.actions.update(this.state.region, width, refresh)
        }
        return null
    }

    onPortalClick = (guid: string, coords: LatLng) => {
        if (this.state.selectedPortal && this.state.selectedPortal.guid == guid) {
            this.setState({ selectedPortal: false })
        } else {
            this.setState({ selectedPortal: { guid, coords } })
        }
    }

    onPortalDismiss = () => {
        this.setState({ selectedPortal: false })
    }

    onOpenPortal = (guid: string, coords: LatLng) => {
        const navigateAction = NavigationActions.navigate({
            routeName: 'Portal',
            params: { guid, coords },
        });
        this.props.navigation.dispatch(navigateAction);
    }

    goToMe = () => {
        this.map.animateToCoordinate(this.state.user)
    }

    render() {
        if (!this.state.user) {
            return <View style={styles.spinnerContainer}><ActivityIndicator size={'large'} /></View>
        }
        const initialRegion = this.props.settings.region || { ...this.state.user, latitudeDelta: 0.002, longitudeDelta: 0.002 }
        return (
            <>
                <StatusBar
                    backgroundColor="blue"
                    barStyle="dark-content"
                />
                <MapView
                    ref={r => (r != null) ? this.map = r : null}
                    style={styles.container}
                    initialRegion={initialRegion}
                    onRegionChangeComplete={this.onRegionChange}
                    showsCompass={false}
                    showsScale
                    showsUserLocation
                    userLocationAnnotationTitle=""
                    showsMyLocationButton
                    loadingEnabled
                    type={'hybrid'}
                    shouldRasterizeIOS
                    renderToHardwareTextureAndroid
                >
                    <MapObjects
                        onPortalClick={this.onPortalClick}
                        region={this.state.region || initialRegion}
                        levels={this.props.settings.filterLevel}
                        selectedPortal={this.state.selectedPortal}
                        zoom={this.state.dataZoom}
                    />
                </MapView>
                <MapOverlay
                    goToMe={this.goToMe}
                    refresh={this.refresh}
                    loading={this.props.entities.loadQueue.length}
                    selectedPortal={this.state.selectedPortal}
                    onOpenPortal={this.onOpenPortal}
                    getPortalDetails={this.props.actions.getPortalDetails}
                    portal={this.state.selectedPortal && this.props.entities.portals[this.state.selectedPortal.guid]}
                />
            </>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
});

export default connect({ 'entities': 'entities', 'settings': 'settings' }, actions)(Map)