import React, { useCallback, Fragment, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import Styled from 'styled-components/native';
import Theme from '~/Themes';
import Icon from '../UIControls/Icon';
import Input from '~/Components/UIControls/Input';
import { Selectbox } from '../UIControls/Selectbox';
import EntitySelect from '~/Components/EntitySelect';
import Button from '../UIControls/Button';
import { setCallbackAction, removeCallbackAction } from '~/GlobalReducers/form';
import { ActivityIndicator, View } from 'react-native';
import { DateTimePicker } from '../UIControls/DateTimePicker';
import { MonthPicker } from '~/Components/UIControls/MonthPicker';
import UploadFile from '../UIControls/UploadFile';
import Switch from '../UIControls/Switch';
import { SelectButton } from '../UIControls/SelectButton';
import { Util } from '~/Utils/utils';
import KeyboardAwareScrollView from '@pietile-native-kit/keyboard-aware-scrollview';
import _ from 'lodash';
import PopupSelect from '../UIControls/PopupSelect';

export default Form = {
    VIEW: 'view',
    EDIT: 'edit',
    CREATE: 'create',
    StyledContainer: Styled(KeyboardAwareScrollView)`
        width: 100%;
        padding: 15px;
        padding-top: 15px;
        flex-direction: column;
        background-color: #ffffff;
    `,

    NonScrollStyledContainer: Styled.View`
        width: 100%;
        padding: 15px;
        padding-top: 15px;
        flex-direction: column;
        background-color: #ffffff;
    `,

    Field: Styled.View`
        flex-direction: row;
        width: 100%;
        margin-top: 10px;
    `,

    Group: Styled.View`
        flex-direction: column;
        flex: 1;
    `,

    StyledError: Styled.View`
        flex-direction: row;
        width: 100%;
        height: 16px;
        align-items: flex-start;
        justify-content: flex-end;
        padding-right: 5px;
        padding-top: 2px;
    `,
    Message: Styled.Text`
        position: absolute;
        font-size: 14;
        line-height: 18;
        font-family: ${Theme.Fonts.Medium};
        include-font-padding: false;
        color: ${Theme.COLORS.ERROR};
    `,

    Title: Styled.View`
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        padding-left: 3px;
        padding-right: 3px;
        width: 75px;
        margin-right:10px;
    `,

    Label: Styled.Text`
        font-size: 16;
        font-family: ${Theme.Fonts.Regular};
        include-font-padding: false;
        line-height: 24;
        letter-spacing: -1.6;
        color: #000000;
    `,

    FieldSet: Styled.View`
        width: 100%;
        padding: 20px;
        padding-top: 5px;
        padding-bottom: 5px;
    `,

    FieldSetHead: Styled.View`
        align-self: center;
        width: 98%;
        margin-top:20px;
        border: 0px solid #9aa3ac;
        border-bottom-width: 1px;
    `,

    Legend: Styled.View`
        align-self: flex-start;
        height: 35px;
        border: 0px;
        justify-content: center;
        margin-left:10px;
        padding-left:20px;
        padding-right:20px;
        background-color: #9aa3ac;
        border-top-left-radius:5px;
        border-top-right-radius:5px;
        overflow:hidden;
    `,

    ButtonGroup: Styled.View`
        position: absolute;
        width: 100%;
        height: 35px;
        flex-direction: row;
        justify-content: flex-end;
        padding-right:15px;
    `,

    HeadButton: Styled.TouchableOpacity`
        align-self: center;
        height: 32px;
        border: 0px;
        justify-content: center;
        margin-left:10px;
        padding-left:20px;
        padding-right:20px;
        background-color: #0b83e6;
        border-radius:5px;
        overflow:hidden;
    `,

    LegendLabel: Styled.Text`
        font-size: 16;
        font-family: ${Theme.Fonts.Regular};
        include-font-padding: false;
        line-height: 24;
        letter-spacing: -1.6;
        color: white;
    `,

    SeparateLine: Styled.View`
        width: 99%;
        left: 0.5%;
        min-height: 5px;
        background-color: #9aa3ac;
        margin-top: 20px;
        border-top-left-radius:5px;
        border-top-right-radius:5px;
        overflow:hidden;
    `,

    SeparateLabel: Styled.Text`
        font-size: 16;
        font-family: ${Theme.Fonts.Bold};
        include-font-padding: false;
        line-height: 40px;
        text-align-vertical: center;
        text-align: center;
        height: 40px;
        letter-spacing: -1.6;
        color: white;
    `,

    Require: ({children, style={}, iconFamily="FontAwesome5", iconName="star-of-life"}) => {
        return (
            <Form.Title style={style}>
                {children}
                <Icon iconFamily={iconFamily} iconName={iconName} size={8} color="red" style={{ paddingLeft:2, paddingRight:2 }} />
            </Form.Title>
        )
    },

    TitleTop: ({style={}, ...rest}) => {
        return (<Form.Title style={{alignSelf:'flex-start', marginTop: 8, ...style}} {...rest} />)
    },

    RequireTop: ({style={}, ...rest}) => {
        return (<Form.Require style={{alignSelf:'flex-start', marginTop: 8, ...style}} {...rest} />)
    },

    Loading: () => {
        return (
            <View style={{position:'absolute',left:0,top:0,width:'100%',height:'100%',justifyContent:'center',alignItems:'center' }}>
                <ActivityIndicator size="large" color="#0b83e6" />
            </View>
        )
    },

    Input: Styled(Input)`
        flex: 1;
    `,

    Select: Styled(Selectbox)`
        flex: 1;
    `,

    EntitySelect: Styled(EntitySelect)`
        flex: 1;
    `,

    DatePicker: Styled(DateTimePicker)`
        flex: 1;
    `,
    MonthPicker: Styled(MonthPicker)`
        flex: 1;
    `,

    UploadFile: Styled(UploadFile)`
    `,

    Switch: Styled(Switch)`
    `,

    SelectButton: Styled(SelectButton)`
    `,

    PopupSelect: Styled(PopupSelect)`
    `,

    Container: ({id="form", style={}, children, onEdit=()=>{}, onCancelEdit=()=>{}, onSave=()=>{}, onDelete=()=>{}, onAction=(action)=>{}, loading=false, noEvent=false, scrolling=true}) => {
        const dispatch = useDispatch();
        const setCallback = useCallback((callbacks) => dispatch(setCallbackAction(callbacks)));
        const removeCallback = useCallback((id) => dispatch(removeCallbackAction(id)));

        useEffect(() => {
            if(!noEvent) setCallback({id: id, callbacks: { onEdit, onCancelEdit, onSave, onDelete, onAction }});
        }, [onEdit, onCancelEdit, onSave, onDelete, onAction]);

        useEffect(() => () => {
            if(!noEvent) removeCallback(id);
        }, []);

        return (
            <Fragment>
                {scrolling ? (
                    <Form.StyledContainer style={[style]} extraHeight={24}>{children}</Form.StyledContainer>
                ) : (
                    <Form.NonScrollStyledContainer style={[style]} extraHeight={24}>{children}</Form.NonScrollStyledContainer>
                )}
                {loading && <Form.Loading />}
            </Fragment>
        )
    },

    PrimaryButton: ({children, buttonStyle={}, textStyle={}, style={}, onPress=()=>{}}) => {
        return (
            <Button style={[style]} buttonStyle={{ 
                width:70, height:31, borderRadius:5,
                backgroundColor: '#0b83e6',
                borderWidth: 1, borderColor: '#0b83e6',
                ...buttonStyle
            }} textStyle={{
                color: 'white',
                fontFamily: Theme.Fonts.Regular,
                fontSize: 14,
                lineHeight: 20,
                letterSpacing: -1.4, ...textStyle
            }} onPress={onPress}>{children}</Button>
        )
    },
    DefaultButton: ({children, buttonStyle={}, textStyle={}, style={}, onPress=()=>{}}) => {
        return (
            <Button style={[style]} buttonStyle={{ 
                width:70, height:31, borderRadius:5,
                backgroundColor: '#ffffff',
                borderWidth: 1, borderColor: '#0b83e6',
                ...buttonStyle
            }} textStyle={{
                color: '#0b83e6',
                fontFamily: Theme.Fonts.Regular,
                fontSize: 14,
                lineHeight: 20,
                letterSpacing: -1.4, ...textStyle
            }} color="white" onPress={onPress}>{children}</Button>
        )
    },
    EditButton: ({id="form", type="", navigation, buttonStyle={}, onPress=()=>{}}) => {
        const allCallbacks = useSelector(({ GlobalForm }) => GlobalForm.callbacks);
        const callbacks = typeof allCallbacks[id] === 'undefined' ? allCallbacks.default : allCallbacks[id];
        const handler = () => { 
            callbacks.onEdit(); 
            onPress(); 
            navigation.setParams({editable:true});
        };
        return (
            type == "primary" ? (
                <Form.PrimaryButton buttonStyle={buttonStyle} onPress={handler}>편집</Form.PrimaryButton>
            ) : (
                <Form.DefaultButton buttonStyle={buttonStyle} onPress={handler}>편집</Form.DefaultButton>
            )
        )
    },
    DeleteButton: ({id="form", type="", buttonStyle={}}) => {
        const allCallbacks = useSelector(({ GlobalForm }) => GlobalForm.callbacks);
        const callbacks = typeof allCallbacks[id] === 'undefined' ? allCallbacks.default : allCallbacks[id];
        const handler = () => { callbacks.onDelete() };
        return (
            type == "primary" ? (
                <Form.PrimaryButton onPress={handler} buttonStyle={{backgroundColor:'#FE2472', borderColor:'#FE2472',...buttonStyle}}>삭제</Form.PrimaryButton>
            ) : (
                <Form.DefaultButton onPress={handler} buttonStyle={buttonStyle}>삭제</Form.DefaultButton>
            )
        )
    },
    SaveButton: ({id="form", type="", buttonStyle={}}) => {
        const allCallbacks = useSelector(({ GlobalForm }) => GlobalForm.callbacks);
        const callbacks = typeof allCallbacks[id] === 'undefined' ? allCallbacks.default : allCallbacks[id];
        const handler = () => { callbacks.onSave() };
        return (
            type == "primary" ? (
                <Form.PrimaryButton onPress={handler} buttonStyle={{backgroundColor:'#0EB118',borderColor:'#0EB118',...buttonStyle}}>저장</Form.PrimaryButton>
            ) : (
                <Form.DefaultButton onPress={handler} buttonStyle={{borderColor:'#0EB118',...buttonStyle}} textStyle={{color:'#0EB118'}}>저장</Form.DefaultButton>
            )
        )
    },
    CancelEditButton: ({id="form", type="", navigation, buttonStyle={}, onPress=()=>{}}) => {
        const allCallbacks = useSelector(({ GlobalForm }) => GlobalForm.callbacks);
        const callbacks = typeof allCallbacks[id] === 'undefined' ? allCallbacks.default : allCallbacks[id];
        const handler = () => { 
            callbacks.onCancelEdit(); 
            onPress(); 
            navigation.setParams({editable:false});
        };
        return (
            type == "primary" ? (
                <Form.PrimaryButton onPress={handler} buttonStyle={buttonStyle}>취소</Form.PrimaryButton>
            ) : (
                <Form.DefaultButton onPress={handler} buttonStyle={buttonStyle}>취소</Form.DefaultButton>
            )
        )
    },
    ActionButton: ({id="form", type="success", navigation, action, title="", onPress=()=>{}, buttonStyle={}}) => {
        const allCallbacks = useSelector(({ GlobalForm }) => GlobalForm.callbacks);
        const callbacks = typeof allCallbacks[id] === 'undefined' ? allCallbacks.default : allCallbacks[id];
        const handler = () => { 
            callbacks.onAction(action);
            onPress();
        };
        return (
            type == "" ? (
                <Form.DefaultButton buttonStyle={buttonStyle} onPress={handler}>{title}</Form.DefaultButton>
            ) : (
                <Form.PrimaryButton onPress={handler} buttonStyle={{
                    backgroundColor:Theme.getColorNameToColor(type),
                    borderColor:Theme.getColorNameToColor(type),
                    ...buttonStyle
                }}>{title}</Form.PrimaryButton>
            )
        )
    },

    Error: ({message=null}) => {
        let msg = message;
        if(Array.isArray(message)) {
            msg = null;
            for(let m of message) {
                if(m) {
                    msg = m;
                    break;
                }
            }
        }
        return (msg && <Form.StyledError><Form.Message>{msg.message}</Form.Message></Form.StyledError>);
    },
    Regist: ({name, value, rule, type, error=null}) => {
        useEffect(() => {
            if(name) {
                Form.register(name, value, rule, type);
            }
        }, []);
        return (<Form.Error message={error} />);
    },
    RegistFile: ({name, value, rule=null, error=null}) => {
        useEffect(() => {
            if(name) {
                Form.register(`${name}.IsUpload`, false, null, null);
                Form.register(`${name}.IsDelete`, false, null, null);
                Form.register(`${name}.Name`, Util.get(value, "Name"), rule, null);
                Form.register(`${name}.Url`, Util.get(value, "Url"), null, null);
                Form.register(`${name}.Path`, Util.get(value, "Path"), null, null);
                Form.register(`${name}.FileSize`, "", null, null);
                Form.register(`${name}.ContentType`, "", null, null);
            }
        }, []);

        return (<Form.Error message={error} />);
    },

    formData: {},
    useFormRegister: () => {},
    useFormSetValue: () => {},
    setFormData: (data) => {
        Form.formData = data;

        for(let name in data) {
            const value = data[name];
            let isSet = false;
            if(typeof value === 'object' && value != null) {
                const keys = Object.keys(value);
                if(keys.find(v => v == 'Name')
                && keys.find(v => v == 'Url')
                && keys.find(v => v == 'Path')) {
                    isSet = true;
                    Form.useFormSetValue(`${name}.Name`, Util.get(value, "Name"), false);
                    Form.useFormSetValue(`${name}.Url`, Util.get(value, "Url"), false);
                    Form.useFormSetValue(`${name}.Path`, Util.get(value, "Path"), false);
                    Form.useFormSetValue(`${name}.FileSize`, Util.get(value, "FileSize"), false);
                    Form.useFormSetValue(`${name}.ContentType`, Util.get(value, "ContentType"), false);
                }
            }
            if(!isSet) {
                Form.useFormSetValue(name, value, false);
            }
        }
    },
    clear: () => {
        Form.formData = {};
    },
    setUseFormFunctions: (register, setValue, getValues) => {
        Form.clear();
        Form.useFormRegister = register;
        Form.useFormSetValue = setValue;
        Form.useFormGetValues = getValues;
    },
    register: (name, value, validationOptions={}, type) => {
        const obj = (typeof type === 'undefined' || type == null) ? {name:name} : {name:name, type:type};
        Form.useFormRegister(obj, validationOptions);

        if(typeof value === 'undefined') {
            const data = Form.formData;
            value = _.get(data, name, '');
            /*
            value = data[name];
            if(typeof value === 'undefined') {
                value = '';
            }
            */
        }
        Form.useFormSetValue(name, value, false);
    },
    registers: (validates = []) => {
        for(let validate of validates) {
            if(typeof validate === 'string') {
                Form.register(validate)
            } else {
                /* {name, value, rule, type} */
                const name = validate.name;
                const value = validate.value;
                const rule = validate.rule;
                const type = validate.type;

                Form.register(name, value, rule, type);
            }
        }
    },
    uploadFile: (name, isUpload, result) => {
        Form.useFormSetValue(`${name}.IsUpload`, isUpload, false);
        Form.useFormSetValue(`${name}.Name`, result.Name, false);
        Form.useFormSetValue(`${name}.Url`, result.Url, false);
        Form.useFormSetValue(`${name}.Path`, result.Path, false);
        Form.useFormSetValue(`${name}.FileSize`, result.FileSize, false);
        Form.useFormSetValue(`${name}.ContentType`, result.ContentType, false);
        if(isUpload) Form.useFormSetValue(`${name}.IsDelete`, false, false);
    },
    deleteFile: (name) => {
        Form.useFormSetValue(`${name}.IsDelete`, true, false);
        Form.useFormSetValue(`${name}.IsUpload`, false, false);
    },
}