import React, { useCallback, Fragment, useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import Styled from 'styled-components/native';
import { View, ToastAndroid, Platform, Alert, Text, Keyboard, Modal, Animated } from 'react-native';
import { promptOpenAction } from '~/GlobalReducers/prompt';
import { addMessageAction, removeMessageAction } from '~/GlobalReducers/message';
import Theme from '~/Themes';
import Input from './Input';
import Button from './Button';

export const useToast = () => {
    const dispatch = useDispatch();
    const addMessage = useCallback((message) => dispatch(addMessageAction(message)), []);
    const removeMessage = useCallback((id) => dispatch(removeMessageAction(id)), []);

    const showToastMessage = (message) => {
        const id = `${Math.random()}`;
        addMessage({id:id,message:message, hide:false});
        setTimeout(() => {
            removeMessage(id);
        }, 4000);
    }

    return { showMessage: showToastMessage };
}

export const showMessage = (message) => {
    if(Platform.OS == "android") {
        ToastAndroid.show(message, ToastAndroid.LONG);
    } else if(Platform.OS == "ios") {
        Alert.alert(message);
    }
}

const MessageContainer = Styled(Animated.View)`
    position: absolute;
    left: 20px;
    right: 20px;
    bottom: 100px;
    align-items: center;
    justify-content: center;
`;
const MessageView = Styled.View`
    background-color: black;
    border-radius: 8px;
    opacity: 0.7;
    padding: 10px;
    padding-left: 20px;
    padding-right: 20px;
    overflow: hidden;
`;
const MessageInnerText = Styled.Text`
    font-family: ${Theme.Fonts.Medium};
    font-size: 16;
    line-height: 20;
    letter-spacing: -1.2;
    color: transparent;
`;
const MessageTransparentView = Styled.TouchableOpacity`
    position: absolute;
    background-color: transparent;
    border-radius: 8px;
    opacity: 1;
    padding: 10px;
    padding-left: 20px;
    padding-right: 20px;
    overflow: hidden;
`;
const MessageText = Styled.Text`
    font-family: ${Theme.Fonts.Medium};
    font-size: 16;
    line-height: 20;
    letter-spacing: -1.2;
    color: white;
`;

const MessageAnimatedContainer = ({children, message, index}) => {
    const [opacityValue] = useState(new Animated.Value(0));
    const [positionValue] = useState(new Animated.ValueXY({x:0, y:100}));

    useEffect(() => {
        Animated.timing(opacityValue, {
            toValue: 1,
            duration: 400,
            useNativeDriver: true,
        }).start();
        Animated.timing(positionValue, {
            toValue: {x:0,y:0},
            duration: 150,
            useNativeDriver: true,
        }).start();

        setTimeout(() => {
            Animated.timing(opacityValue, {
                toValue: 0,
                duration: 400,
                useNativeDriver: true,
            }).start();
        }, 3000);
    }, []);

    return (
        <MessageContainer style={{
            opacity:opacityValue,
            transform:[{ translateX:positionValue.x }, { translateY: positionValue.y }] 
        }}>{children}</MessageContainer>
    );
}

export const MessageProvider = () => {
    const messages = useSelector(({ GlobalMessage }) => GlobalMessage.messages);
    const dispatch = useDispatch();
    const removeMessage = useCallback((id) => dispatch(removeMessageAction(id)), []);

    return (
        <Fragment>
        {messages.map((value, index) => {
            return (
                <MessageAnimatedContainer key={`toast-message-${value.id}`} message={value} index={index}>
                    <MessageView>
                        <MessageInnerText>{value.message}</MessageInnerText>
                    </MessageView>
                    <MessageTransparentView onPress={() => { removeMessage(value.id) }}>
                        <MessageText>{value.message}</MessageText>
                    </MessageTransparentView>
                </MessageAnimatedContainer>
            );
        })}
        </Fragment>
    )
}

export const alert = (title, message) => {
    Alert.alert(title, message);
}

export const confirm = (title, message, confirm=()=>{}, cancel=()=>{}) => {
    Alert.alert(title, message, [
        {text:'취소', onPress:cancel, style:'cancel'},
        {text:'확인', onPress:confirm},
    ], {cancelable:false});
}

export const usePrompt = () => {
    const dispatch = useDispatch();
    const promptOpen = useCallback((prompt) => dispatch(promptOpenAction(prompt)), []);

    return {
        prompt: ({title="", message="", defaultValue="", confirm=(text)=>{}, cancel=()=>{}, inputStyle={}, component=null, componentProps={}}) => {
            promptOpen({
                show: true, title:title, message:message, 
                defaultValue:defaultValue, onConfirm:confirm, onCancel:cancel, 
                inputStyle:inputStyle, component:component, componentProps:componentProps
            });
        }
    };
}

const PromptContainer = Styled.View`
    width:100%;
    height:100%;
    background-color: transparent;
    align-items: center;
    justify-content: center;
`;
const PromptBackground = Styled.TouchableOpacity`
    position: absolute;
    width: 100%; height:100%;
    padding: 20px;
    background-color: black; opacity:0.7;
`;
const PromptContent = Styled.View`
    width:80%;
    padding: 10px;
    background-color: white;
    border-radius: 5px;
    flex-direction: column;
`;
const PromptTitle = Styled.Text`
    font-family: ${Theme.Fonts.Medium};
    font-size: 18;
    line-height: 25;
    letter-spacing: -1.6;
    color: black;
    width: 100%;
    padding: 10px;
`;
const PromptMessage = Styled.Text`
    font-family: ${Theme.Fonts.Light};
    font-size: 16;
    line-height: 20;
    letter-spacing: -1.2;
    color: #555555;
    width:100%;
    padding: 10px;
    padding-top: 0px;
`;
const PromptInputContainer = Styled.View`
    width: 100%;
    padding: 10px;
`;
const PromptButtonContainer = Styled.View`
    width: 100%;
    flex-direction: row;
    justify-content: flex-end;
    padding: 10px;
`;
const PromptConfirmButtonStyle = {
    Button: {
        width:70, height:31, borderRadius:5,
        backgroundColor: '#0b83e6',
        borderWidth: 1, borderColor: '#0b83e6',
    },
    Text: {
        color: 'white',
        fontFamily: Theme.Fonts.Regular,
        fontSize: 14,
        lineHeight: 20,
        letterSpacing: -1.4
    }
};
const PromptCancelButtonStyle = {
    Button: {
        width:70, height:31, borderRadius:5,
        backgroundColor: '#ffffff',
        borderWidth: 1, borderColor: '#0b83e6',
    },
    Text: {
        color: '#0b83e6',
        fontFamily: Theme.Fonts.Regular,
        fontSize: 14,
        lineHeight: 20,
        letterSpacing: -1.4
    }
};

export const PromptProvider = () => {
    const payload = useSelector(({ GlobalPrompt }) => GlobalPrompt.prompt);
    const dispatch = useDispatch();
    const promptOpen = useCallback((prompt) => dispatch(promptOpenAction(prompt)), []);
    const [result, setResult] = useState(payload.defaultValue);

    useEffect(() => {
        if(payload.show) {
            Keyboard.dismiss();
        }
        setResult(payload.defaultValue);
    }, [payload]);

    const CustomComponent = payload.component;

    return (
        payload.show ? (
            <Modal animationType="fade" transparent={true}>
                <PromptContainer>
                    <PromptBackground onPress={() => { 
                        payload.onCancel(); 
                        promptOpen({show:false}); 
                    }} />
                    <PromptContent>
                        {payload.title && <PromptTitle>{payload.title}</PromptTitle>}
                        {payload.title && <PromptMessage>{payload.message}</PromptMessage>}
                        <PromptInputContainer>
                            {CustomComponent ? (
                                <CustomComponent onChange={(value) => {
                                    setResult(value);
                                }} {...payload.componentProps} />
                            ) : (
                                <Input style={payload.inputStyle}
                                onChangeText={(value) => {
                                    setResult(value);
                                }} />
                            )}
                        </PromptInputContainer>
                        <PromptButtonContainer>
                            <Button buttonStyle={PromptCancelButtonStyle.Button} 
                                textStyle={PromptCancelButtonStyle.Text}
                                onPress={() => { 
                                    promptOpen({show:false});
                                    payload.onCancel();
                                }}>취소</Button>
                            <Button buttonStyle={PromptConfirmButtonStyle.Button} 
                                textStyle={PromptConfirmButtonStyle.Text}
                                onPress={() => { 
                                    const event = { autoClose:true, close:()=>{ promptOpen({show:false}) } };
                                    payload.onConfirm(result, event);
                                    if(event.autoClose) {
                                        promptOpen({show:false});
                                    }
                                }}>확인</Button>
                        </PromptButtonContainer>
                    </PromptContent>
                </PromptContainer>
            </Modal>
        ) : (
            <Fragment/>
        )
    );
}
