import React from 'react';
import { number, string, bool, oneOfType } from 'prop-types';
import { ViewPropTypes, requireNativeComponent, Image, ImageSourcePropType, Platform } from 'react-native';
import type { NaviLatLng, NaviPoi, NaviLocation, NaviCalculateRouteResult, NaviType, NaviShowMode, NaviTrackingMode } from '../types';
import Component from '../map-view/component';

import { mapEventsPropType, NaviShowModePropType, NaviTrackingModePropType, WalkNaviPointPropType } from '../prop-types';

export type WalkNaviPointProp = NaviLatLng | NaviPoi | Array<NaviLatLng | NaviPoi>;

export interface WalkNaviViewProp {
    /**
     * 导航起点，不指定则从当前位置开始导航
     */
    from?: WalkNaviPointProp;
    /**
     * 导航目的地
     */
    to: WalkNaviPointProp;
    /**
     * 导航策略
     */
    strategy?: number;
    /**
     * 导航UI是否可见（默认可见）
     */
    layoutVisible?: boolean;
    /**
     * 指南针图标否在导航界面显示，默认显示。
     */
    compassVisible?: boolean;
    /**
     * 起始终点线颜色
     */
    leaderLineColor?: string;
    /**
     * 导航状态下屏幕是否常亮
     */
    screenAlwaysBright?: boolean;
    /**
     * 是否显示路线全览按钮
     */
    browseButtonVisible?: boolean;
    /**
     * 更多按钮是否显示
     */
    moreButtonVisible?: boolean;
    /**
     * 比例尺是否显示
     */
    scaleVisible?: boolean;
    /**
     * 转向箭头是否显示
     */
    turnArrowVisible?: boolean;
    /**
     * 设置锁车下地图倾角 倾角为0时地图模式是2D模式。
     */
    tilt?: number;

    carMarkerIcon?: ImageSourcePropType;
    startMarkerIcon?: ImageSourcePropType;
    endMarkerIcon?: ImageSourcePropType;
    fourCornersIcon?: ImageSourcePropType;
    /**
     * 设置导航界面跟随模式
     */
    trackingMode?: NaviTrackingMode;
    /**
     * 导航显示模式
     */
    showMode?: NaviShowMode;
    /**
     * 导航组件初始化失败时分发
     */
    onInitNaviFailure?: () => void;
    /**
     * 导航组件初始化成功时分发
     */
    onInitNaviSuccess?: () => void;
    /**
     * 开始导航时分发
     */
    onStartNavi?: (event: { type: number }) => void;
    /**
     * 位置信息发生变化时分发
     */
    onLocationChange?: (event: NaviLocation) => void;
    /**
     * 导航语音播报时分发
     */
    onGetNavigationText?: (event: { text: string }) => void;
    /**
     * 模拟导航结束时分发
     */
    onEndEmulatorNavi?: () => void;
    /**
     * 路径计算失败时分发
     */
    onCalculateRouteFailure?: (event: NaviCalculateRouteResult) => void;
    /**
     * 路径计算成功时分发
     */
    onCalculateRouteSuccess?: (event: NaviCalculateRouteResult) => void;
    /**
     * 响铃时分发
     */
    onPlayRing?: (event: { type: number }) => void;
    /**
     * GPS信号改变时分发
     */
    onGpsStatusChanged?: (event: { status: number }) => void;
    /**
     * 导航设置发生改变时分发
     */
    onNaviSettingChanged?: () => void;
    /**
     * 导航取消时分发
     */
    onNaviCancel?: () => void;
    /**
     * 导航完成时分发
     */
    onNaviComplete?: () => void;
    /**
     * 地图加载完成时分发
     */
    onNaviViewLoaded?: () => void;
    /**
     * 点击导航返回按钮时分发
     */
    onNaviBackClick?: () => void;
    /**
     * 点击全览按钮时分发
     */
    onScanViewButtonClick?: () => void;
    /**
     * 导航地图模式改变时分发（锁车、全览、普通）
     */
    onNaviMapModeChanged?: (event: { mode: number }) => void;
    /**
     * 地图类型发生改变时分发（白天、黑夜模式）
     */
    onNaviMapViewModeChanged?: (event: { type: number }) => void;

    /**
     * 导航界面跟随模式改变后分发
     */
    onNaviMapViewTrackingModeChanged?: (event: { mode: number }) => void;
    /**
     * 地图锁定时分发
     */
    onLockMap?: (event: { isLock: boolean }) => void;
}

const events = [
    'onInitNaviFailure',
    'onInitNaviSuccess',
    'onStartNavi',
    'onLocationChange',
    'onGetNavigationText',
    'onEndEmulatorNavi',
    'onCalculateRouteFailure',
    'onCalculateRouteSuccess',
    'onGpsStatusChanged',
    'onNaviSettingChanged',
    'onNaviCancel',
    'onNaviComplete',
    'onNaviViewLoaded',
    'onNaviBackClick',
    'onScanViewButtonClick',
    'onNaviMapModeChanged',
    'onNaviMapViewModeChanged',
    'onNaviMapViewTrackingModeChanged',
    'onLockMap',
];

export class WalkNaviView extends Component<WalkNaviViewProp> {
    static propTypes = {
        ...ViewPropTypes,
        ...mapEventsPropType(events),
        from: WalkNaviPointPropType,
        to: WalkNaviPointPropType.isRequired,
        strategy: number,
        layoutVisible: bool,
        compassVisible: bool,
        leaderLineColor: string,
        screenAlwaysBright: bool,
        browseButtonVisible: bool,
        moreButtonVisible: bool,
        scaleVisible: bool,
        turnArrowVisible: bool,
        trackingMode: NaviTrackingModePropType,
        tilt: number,
        carMarkerIcon: oneOfType([string, number]),
        startMarkerIcon: oneOfType([string, number]),
        endMarkerIcon: oneOfType([string, number]),
        fourCornersIcon: oneOfType([string, number]),
        showMode: NaviShowModePropType,
    };

    static defaultProps = {
        strategy: 10, // 单路径
    };

    startNavi(type: NaviType, speed?: number): void {
        this.call('startNavi', [type, speed || 60]);
    }

    stopNavi(): void {
        this.call('stopNavi', []);
    }

    pauseNavi(): void {
        this.call('puaseNavi', []);
    }

    resumeNavi(): void {
        this.call('resumeNavi', []);
    }

    startGPS(time?: number, dis?: number): void {
        this.call('startPGS', [time, dis]);
    }

    stopGPS(): void {
        this.call('stopGPS', []);
    }

    nativeComponent = 'AWalkNaviView';

    render() {
        let { from, to, strategy, ...restProps } = this.props;
        if (from && !Array.isArray(from) && Platform.OS === 'ios') {
            from = [from];
        }
        if (to && !Array.isArray(to) && Platform.OS === 'ios') {
            to = [to];
        }
        if (from && Array.isArray(from) && Platform.OS === 'android') {
            from = from[0];
        }
        if (to && Array.isArray(to) && Platform.OS === 'android') {
            to = to[0];
        }
        const props: { [key: string]: any } = {
            ...restProps,
            ...this.handlers(events),
            navi: { from, to, strategy },
        };
        for (let k in props) {
            if (k.indexOf('Icon') > -1) {
                props[k] = Image.resolveAssetSource(props[k]);
            }
        }
        return <AWalkNaviView {...props} />;
    }
}

// @ts-ignore
const AWalkNaviView = requireNativeComponent('AWalkNaviView', WalkNaviView);
