import { Dimensions, Linking } from 'react-native';
import { Svgs } from '~/Generated/Svgs';
import { NavigationActions } from 'react-navigation';
import session from './session';
import _ from 'lodash';
import moment from 'moment';
import { Config } from '~/Configuration';

export const Util = {
    getStatusBarHeight: () => {
        return Expo.Constants.statusBarHeight;
    },
    getScreenSize: () => {
        return Dimensions.get('window');
    },
    getScreenWidth: () => {
        return Util.getScreenSize().width;
    },
    getScreenHeight: () => {
        return Util.getScreenSize().height;
    },
    getBottomTabBarHeight: (tabCount = 5) => {
        return Math.round(Util.getScreenWidth() / tabCount);
    },
    getContentHeight: (headerHeight = 50, tabCount = 5) => {
        console.log(Util.getScreenHeight(), Util.getStatusBarHeight(), headerHeight, Util.getBottomTabBarHeight(tabCount));
        return Util.getScreenHeight() - Util.getStatusBarHeight() - headerHeight - Util.getBottomTabBarHeight(tabCount);
    },

    toDate: (date) => {
        if (typeof date === 'string') {
            if (date.split('T').length == 2 && date.indexOf('Z') == -1) {
                const regexp = /([0-9]{4})\-([0-9]{1,2})\-([0-9]{1,2})[T]{1}([0-9]{1,2})\:([0-9]{1,2})\:([0-9]{1,2})[\.]*([0-9]{0,3})/g;
                const matches = regexp.exec(date);
                date = new Date(
                    matches[1],
                    parseInt(matches[2]) - 1,
                    matches[3],
                    matches[4],
                    matches[5],
                    matches[6],
                    matches[7] ? matches[7] : 0,
                );
            } else {
                date = new Date(date);
            }
        }
        if (date instanceof Date) return date;
        if (!date) return new Date();
        return new Date(date);
    },

    formatDate: (date = new Date(), format = 'yyyy-MM-dd hh:mm:ss.zzz', nullValue = '') => {
        if (!date) return nullValue;
        if (typeof date === 'string') {
            if (date.split('T').length == 2 && date.indexOf('Z') == -1) {
                const regexp = /([0-9]{4})\-([0-9]{1,2})\-([0-9]{1,2})[T]{1}([0-9]{1,2})\:([0-9]{1,2})\:([0-9]{1,2})[\.]*([0-9]{0,3})/g;
                const matches = regexp.exec(date);
                date = new Date(
                    matches[1],
                    parseInt(matches[2]) - 1,
                    matches[3],
                    matches[4],
                    matches[5],
                    matches[6],
                    matches[7] ? matches[7] : 0,
                );
            } else {
                date = new Date(date);
            }
        }
        if (!date instanceof Date) date = new Date(date);
        if (!date instanceof Date) return nullValue;
        if (typeof date.getFullYear === 'undefined') return nullValue;

        const weeks = ['일', '월', '화', '수', '목', '금', '토'];
        const weeksLong = ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'];
        let result = format;
        result = result.replace('yyyy', date.getFullYear());
        result = result.replace('MM', (date.getMonth() + 1 + '').padStart(2, '0'));
        result = result.replace('dd', (date.getDate() + '').padStart(2, '0'));
        result = result.replace('W', weeksLong[date.getDay()]);
        result = result.replace('w', weeks[date.getDay()]);
        result = result.replace('hh', (date.getHours() + '').padStart(2, '0'));
        result = result.replace('mm', (date.getMinutes() + '').padStart(2, '0'));
        result = result.replace('ss', (date.getSeconds() + '').padStart(2, '0'));
        result = result.replace('zzz', (date.getMilliseconds() + '').padStart(3, '0'));
        return result;
    },

    toMonthString: (date = new Date(), nullValue = '', seperate = '-') => {
        const mv = moment(date);
        if (mv.isValid()) {
            return mv.format('YYYY') + seperate + mv.format('MM');
        } else {
            return '';
        }
    },

    toDateString: (date = new Date(), nullValue = '', seperate = '-') => {
        if (!date) return nullValue;
        if (typeof date === 'string') {
            if (date.split('T').length == 2 && date.indexOf('Z') == -1) {
                const regexp = /([0-9]{4})\-([0-9]{1,2})\-([0-9]{1,2})[T]{1}([0-9]{1,2})\:([0-9]{1,2})\:([0-9]{1,2})[\.]*([0-9]{0,3})/g;
                const matches = regexp.exec(date);
                date = new Date(
                    matches[1],
                    parseInt(matches[2]) - 1,
                    matches[3],
                    matches[4],
                    matches[5],
                    matches[6],
                    matches[7] ? matches[7] : 0,
                );
            } else {
                date = new Date(date);
            }
        }
        if (!date instanceof Date) date = new Date(date);
        if (!date instanceof Date) return nullValue;
        if (typeof date.getFullYear === 'undefined') return nullValue;
        if (date.getFullYear() == 1 && date.getMonth() == 0 && date.getDate() == 1) return nullValue;
        return (
            date.getFullYear() + seperate + (date.getMonth() + 1 + '').padStart(2, '0') + seperate + (date.getDate() + '').padStart(2, '0')
        );
    },

    toDateTimeString: (date = new Date(), nullValue = '', seperate = '-', timeSeperate = ':') => {
        if (!date) return nullValue;
        if (typeof date === 'string') {
            if (date.split('T').length == 2 && date.indexOf('Z') == -1) {
                const regexp = /([0-9]{4})\-([0-9]{1,2})\-([0-9]{1,2})[T]{1}([0-9]{1,2})\:([0-9]{1,2})\:([0-9]{1,2})[\.]*([0-9]{0,3})/g;
                const matches = regexp.exec(date);
                date = new Date(
                    matches[1],
                    parseInt(matches[2]) - 1,
                    matches[3],
                    matches[4],
                    matches[5],
                    matches[6],
                    matches[7] ? matches[7] : 0,
                );
            } else {
                date = new Date(date);
            }
        }
        if (!date instanceof Date) date = new Date(date);
        if (!date instanceof Date) return nullValue;
        if (typeof date.getFullYear === 'undefined') return nullValue;
        if (date.getFullYear() == 1 && date.getMonth() == 0 && date.getDate() == 1) return nullValue;
        let result = '';
        result +=
            date.getFullYear() +
            seperate +
            (date.getMonth() + 1 + '').padStart(2, '0') +
            seperate +
            (date.getDate() + '').padStart(2, '0') +
            ' ' +
            (date.getHours() + '').padStart(2, '0') +
            timeSeperate +
            (date.getMinutes() + '').padStart(2, '0') +
            timeSeperate +
            (date.getSeconds() + '').padStart(2, '0');
        return result;
    },

    get: (obj, property, defaultValue = null) => {
        return _.get(obj, property, defaultValue);
    },

    set: (obj, property, value) => {
        return _.set(obj, property, value);
    },

    nvl: (obj, nullValue = '') => {
        if (obj == null || obj === 'undefined') return nullValue;
        return obj;
    },

    getDate: (obj, property) => {
        return new Date(Util.getDateString(obj, property));
    },

    getMonthString: (obj, property, seperate = '-') => {
        const mv = moment(Util.get(obj, property, ''));
        if (mv.isValid()) {
            return mv.format('YYYY') + seperate + mv.format('MM');
        } else {
            return '';
        }
    },

    getDateString: (obj, property, seperate = '-') => {
        return Util.toDateString(Util.get(obj, property, ''), '', seperate);
    },

    getDateTimeString: (obj, property, dateSeperate = '-', timeSeperate = ':') => {
        return Util.toDateTimeString(Util.get(obj, property, ''), '', dateSeperate, timeSeperate);
    },

    addMonth: (number, date = new Date()) => {
        return new Date(date.setMonth(date.getMonth() + number));
    },

    addYear: (number, date = new Date()) => {
        return new Date(date.setFullYear(date.getFullYear() + number));
    },

    addDate: (number, date = new Date()) => {
        return new Date(date.setDate(date.getDate() + number));
    },

    getFirstDate: (date = new Date()) => {
        return date.getFullYear() + '-' + (date.getMonth() + 1 + '').padStart(2, '0') + '-01';
    },
    getLastDate: (date = new Date()) => {
        var lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
        return date.getFullYear() + '-' + (date.getMonth() + 1 + '').padStart(2, '0') + '-' + (lastDay + '').padStart(2, '0');
    },

    toPrice: (num) => {
        if (!num) return 0;
        return ('' + num).replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
    },
    toInt: (num) => {
        if (!num) return 0;
        let val = 0;
        try {
            val = parseInt(num.replace(/[^0-9]/g, ''));
        } catch {}
        return val;
    },

    svg: (path, name) => {
        let svgPath = path;
        let svgName = name;
        if (!path && !name) return null;
        if (path && name == '{}') {
            let list = {};
            for (let p of Object.keys(Svgs).filter((key) => key.indexOf(path) == 0)) {
                for (let name of Object.keys(Svgs[p])) {
                    list[p + '/' + name] = Svgs[p][name];
                }
            }
            return list;
        }
        if (path && name == '[]') {
            let list = [];
            for (let p of Object.keys(Svgs).filter((key) => key.indexOf(path) == 0)) {
                for (let name of Object.keys(Svgs[p])) {
                    list.push({
                        Path: p + '/' + name,
                        Svg: Svgs[p][name],
                    });
                }
            }
            return list;
        }
        if (typeof name === 'undefined') {
            const idx = path.lastIndexOf('/');
            if (idx == -1) {
                svgPath = '/';
                svgName = path;
            } else {
                svgPath = path.substr(0, idx);
                if (idx + 1 >= path.length) svgName = '';
                else svgName = path.substr(idx + 1);
            }
        }
        if (typeof Svgs[svgPath] === 'undefined') {
            return null;
        }
        if (typeof svgName === 'undefined' || svgName == '') return null;
        if (typeof Svgs[svgPath][svgName] === 'undefined') return null;
        return Svgs[svgPath][svgName];
    },

    undefined: (value) => {
        if (typeof value === 'undefined') return true;
        return false;
    },

    convertGridData: (data, numColumns) => {
        const numberOfFullRows = Math.floor(data.length / numColumns);

        let numberOfElementsLastRow = data.length - numberOfFullRows * numColumns;
        while (numberOfElementsLastRow !== numColumns) {
            data.push({ empty: true });
            numberOfElementsLastRow++;
        }

        return data;
    },

    navigate: (navigation, menu, parentid = null, params = {}) => {
        if (menu == null) return;

        const navigateAction = NavigationActions.navigate({
            routeName: menu.path,
            action: NavigationActions.navigate({
                routeName: 'Index',
                params: {
                    auth: menu.auth,
                    userinfo: session.getUserInfo(),
                    config: session.getSiteConfig(),
                    sitemap: {
                        name: menu.name,
                        auth: menu.auth,
                        path: menu.path,
                        icon: menu.icon,
                        id: menu.id,
                        parentid: parentid == null ? (menu.parent == null ? 0 : menu.parent.id) : parentid,
                    },
                    ...params,
                },
            }),
        });
        navigation.dispatch(navigateAction);
    },

    validPassword: (passwd) => {
        if (/^[0-9a-zA-Z#?!@$%^&*-_+=]{10,}$/.test(passwd) == false) {
            return '비밀번호는 대문자, 소문자, 숫자, 특수문자로 10글자이상 입력해주세요';
        }

        let typeCount = 0;
        for (let reg of [/[0-9]+/, /[a-z]+/, /[A-Z]+/, /[#?!@$%^&\*\-\/_+=]+/]) {
            if (reg.test(passwd)) {
                typeCount++;
            }
        }

        if (typeCount < 2) {
            return '대문자, 소문자, 숫자, 특수문자 중 2개 조합으로 작성해주세요';
        }

        return null;
    },

    parseFloat: (value) => {
        let result = parseFloat(value);
        if (isNaN(result)) {
            return 0;
        }
        return result;
    },

    downloadFile: (file) => {
        if (file.Path && file.Name) {
            Linking.openURL(
                `${Config.BASE_URL}/api/FileDownload/DownloadFile?filePath=${encodeURIComponent(file.Path)}&fileName=${encodeURIComponent(
                    file.Name,
                )}`,
            );
        } else {
            Linking.openURL(file.Url);
        }
    },

    getMeasure: (component) => {
        return new Promise((resolve, reject) => {
            component.measure((x, y, width, height, pageX, pageY) => {
                resolve({ x, y, width, height, pageX, pageY });
            });
        });
    },
};
