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

import { mapEventsPropType, NaviLatLngPropType, DriveNaviPointPropType, NaviPoiPropType, NaviTrackingModePropType } from '../prop-types';

export type DriveNaviPointProp = string | NaviLatLng | NaviPoi | Array<string | NaviLatLng | NaviPoi>;

export interface DriveNaviViewProp {
    /**
     * 导航起点，不指定则从当前位置开始导航
     */
    from?: DriveNaviPointProp;
    /**
     * 导航目的地
     */
    to: DriveNaviPointProp;
    /**
     * 导航途经点
     */
    wayPoints?: Array<string | NaviLatLng | NaviPoi>;
    /**
     * 导航策略
     */
    strategy?: number;
    /**
     * 导航UI是否可见（默认可见）
     */
    layoutVisible?: boolean;
    /**
     * 是否自动缩放地图
     */
    autoChangeZoom?: boolean;

    /**
     * 是否开启自动黑夜模式切换，默认为false，不自动切换
     */
    autoDayNightMode?: boolean;

    /**
     * 是否显示路线上的摄像头气泡
     */
    cameraBubbleVisible?: boolean;

    /**
     * 指南针图标否在导航界面显示，默认显示。
     */
    compassVisible?: boolean;
    /**
     * 是否显示路线转向箭头
     */
    turnArrowVisible?: boolean;

    /**
     * 导航状态下屏幕是否常亮
     */
    screenAlwaysBright?: boolean;

    /**
     * 是否显示路线全览按钮
     */
    browseButtonVisible?: boolean;
    /**
     * 更多按钮是否显示
     */
    moreButtonVisible?: boolean;
    /**
     * 设置锁车下地图倾角 倾角为0时地图模式是2D模式。
     */
    tilt?: number;

    /**
     * 设置路况光柱条是否显示。
     */
    trafficBarVisible?: boolean;

    /**
     * 设置实时交通按钮是否显示。
     */
    trafficButtonVisible?: boolean;
    /**
     * 设置实时交通路线是否显示
     */
    trafficLineVisible?: boolean;

    carMarkerIcon?: ImageSourcePropType;
    startMarkerIcon?: ImageSourcePropType;
    endMarkerIcon?: ImageSourcePropType;
    wayMarkerIcon?: ImageSourcePropType;
    fourCornersIcon?: ImageSourcePropType;

    /**
     * 导航显示模式
     */
    showMode?: NaviShowMode;
    /**
     * 设置导航界面跟随模式
     */
    trackingMode?: NaviTrackingMode;
    /**
     * 导航组件初始化失败时分发
     */
    onInitNaviFailure?: () => void;
    /**
     * 导航组件初始化成功时分发
     */
    onInitNaviSuccess?: () => void;
    /**
     * 开始导航时分发
     */
    onStartNavi?: (event: { type: number }) => void;
    /**
     * 位置信息发生变化时分发
     */
    onLocationChange?: (event: NaviLocation) => void;
    /**
     * 导航语音播报时分发
     */
    onGetNavigationText?: (event: { text: string }) => void;
    /**
     * 模拟导航结束时分发
     */
    onEndEmulatorNavi?: () => void;
    /**
     * 路径计算失败时分发
     */
    onCalculateRouteFailure?: (event: NaviCalculateRouteResult) => void;
    /**
     * 到达途经点时分发
     */
    onArrivedWayPoint?: (event: { wayId: number }) => void;
    /**
     * GPS状态改变时分发
     */
    onGpsStatusChanged?: (event: { status: boolean }) => void;
    /**
     * 路径计算成功时分发
     */
    onCalculateRouteSuccess?: (event: NaviCalculateRouteResult) => void;
    /**
     * 响铃时分发
     */
    onPlayRing?: (event: { type: 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',
    'onArrivedWayPoint',
    'onGpsStatusChanged',
    'onCalculateRouteSuccess',
    'onPlayRing',
    'onNaviSettingChanged',
    'onNaviCancel',
    'onNaviComplete',
    'onNaviViewLoaded',
    'onNaviBackClick',
    'onScanViewButtonClick',
    'onNaviMapModeChanged',
    'onNaviMapViewModeChanged',
    'onNaviMapViewTrackingModeChanged',
    'onLockMap',
];

export class DriveNaviView extends Component<DriveNaviViewProp> {
    static propTypes = {
        ...ViewPropTypes,
        ...mapEventsPropType(events),
        from: DriveNaviPointPropType,
        to: DriveNaviPointPropType.isRequired,
        wayPoints: oneOfType([arrayOf(string), arrayOf(NaviLatLngPropType), arrayOf(NaviPoiPropType)]),
        strategy: number,
        layoutVisible: bool,
        autoChangeZoom: bool,
        autoDayNightMode: bool,
        cameraBubbleVisible: bool,
        compassVisible: bool,
        leaderLineColor: string,
        turnArrowVisible: bool,
        screenAlwaysBright: bool,
        browseButtonVisible: bool,
        moreButtonVisible: bool,
        tilt: number,
        trafficBarVisible: bool,
        trafficButtonVisible: bool,
        trafficLineVisible: bool,
        carMarkerIcon: object,
        startMarkerIcon: object,
        endMarkerIcon: object,
        wayMarkerIcon: object,
        fourCornersIcon: object,
        showMode: number,
        trackingMode: NaviTrackingModePropType,
    };

    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 = 'ADriveNaviView';

    render() {
        let { from, to, wayPoints, 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, wayPoints, strategy },
        };
        for (let k in props) {
            if (k.indexOf('Icon') > -1) {
                props[k] = Image.resolveAssetSource(props[k]);
            }
        }
        return <ADriveNaviView {...props} />;
    }
}

// @ts-ignore
const ADriveNaviView = requireNativeComponent('ADriveNaviView', DriveNaviView);
