<template>
    <div class="y_picker" :style="styleStr">
        <div v-for="(column,columnName) in list"
             :key="columnName"
             @touchstart="fnTouchStart($event,columnName)"
             @touchmove.stop="fnTouchMove($event,columnName)"
             @touchend="fnTouchEnd($event,columnName)"
             @touchcancel="fnTouchEnd($event,columnName)"
             class="y_picker_box">
            <ul v-if="column" :class="column.className" :style="position[columnName]">
                <li v-for='(item,itemIndex) in column.data'
                    :key="itemIndex"
                    :style="'height:'+ height + unit + ';font-size:'+fontSize+';color:'+(mapList[columnName].selected == item.key ? checkColor : '')+';'"
                    :class="'y_picker_column ' + (mapList[columnName].selected == item.key ? 'y_picker_columnChecked':'')"
                    @click="fnChooseByKey(columnName,item.key)"
                >{{item.value}}
                </li>
            </ul>
        </div>

        <div :class="cursorClassStr"
             :style="'height:'+ height + unit + ';line-height:' + height + unit + ';'">
            <div class="y_picker_label"
                 v-for="(column,columnName) in list"
                 :key="columnName"
                 :style="{textIndent:column.style.textIndent,textAlign:column.style.textAlign,color:column.style.color,fontSize:column.style.color}"
                 v-if="column.label">{{column.label}}
            </div>
        </div>
    </div>
</template>

<script>
    import yButton from "./yButton";
    import Vue from "vue";
    import {range, isArray, isString, isNumber, isObject, each} from "../utils/utils";

    export default {
        name: "yPicker",
        components: {
            yButton
        },
        computed: {
            cursorClassStr() {
                return "y_picker_cursor " + " " +
                    (this.cursorClass ? this.cursorClass : "") + " ";

            },
            height() {
                let ret;
                if (this.itemHeight) {
                    ret = this.itemHeight;
                } else {
                    switch (this.itemSize) {
                        case "normal":
                            ret = 44;
                            break;
                        case "small":
                            ret = 34;
                            break;
                    }
                }
                return ret;
            },
            mapList() {
                return this.list;
            },
            middleLength() {
                return Math.floor(this.visibleItemCount / 2)
            },
            position() {
                let ret = {};
                each(this.list, (column, name) => {
                    ret[name] = "transform:translate3d(0," + column.position + this.unit + ",0);transition-duration:" + this.duration / 1000 + "s;transition-timing-function:cubic-bezier(.08,.28,.44,.94);line-height:" + this.height + "px;";
                })
                return ret;
            },
            styleStr() {
                let heightStyle = "";
                if (this.height) {
                    let height = this.height * this.visibleItemCount;
                    heightStyle = "height:" + height + "px";
                }
                return heightStyle;
            }
        },
        data() {
            return {
                isCombo:false,
                columnsNum: 0,
                duration: 0,
                list: {},
                comboBaseList:{},
                minLength:0,
                maxLength:0,
                unit: "px",
                startY: {}
            }
        },
        methods: {
            //改变的时候该做点什么
            fnChange() {
                let selectArr = {};
                let defaultStr = "";
                const self = this;
                for (let key in this.list) {
                    if (this.list.hasOwnProperty(key)) {
                        selectArr[key] = this.list[key].selected;
                        defaultStr = this.list[key].selected;
                    }

                }
                let isChange = false;
                if (this.columnsNum == 1) {
                    selectArr = defaultStr;
                    if(self.valueKey[0]!=selectArr){
                        isChange = true;
                    }
                }
                else{
                    Object.keys(selectArr).forEach(item=>{
                        if(selectArr[item] != self.valueKey[item]){
                            isChange = true;

                        }
                    })
                }
                if(isChange) {
                    this.$emit("update:valueKey", selectArr);
                    this.$emit("valueKey",selectArr)
                }
                return selectArr;
            },
            //选中某个值
            fnChoose(name, index, disEmit) {
                let ccItem = this.list[name];
                if (ccItem && ccItem.data && ccItem.data[index]) {
                    let selectedItem = ccItem.data[index];
                    ccItem.selected = selectedItem.key;
                    ccItem.position = this.height * this.middleLength - index * this.height;
                    if (!disEmit) {
                        if(this.isCombo){
                            this.fnComboSelect(parseInt(name)+1);
                        }
                        this.fnChange();
                    }
                }
            },
            fnChooseByKey(name, key, disEmit) {
                let self = this;
                let ccItem = self.list[name];
                let ret = false;
                if (ccItem && ccItem.data) {
                    each(ccItem.data, (value, index) => {
                        if (value && value.key == key) {
                            self.fnChoose(name, index, disEmit);
                            ret = true;
                            return false;
                        }
                    })
                }
                return ret;
            },
            fnCheckValue(val) {
                return (isString(val) || isNumber(val)) && val !== "" && val !== undefined
            },
            //检查是否选中
            fnCheckSelect(columnName, key) {
                return this.list[columnName].selected == key;
            },
            fnFormat(arr){
                let ret = [];
                arr.forEach((item, index) => {
                    //对象
                    if (item && isObject(item)) {
                        if(item.value) {
                            ret.push({
                                value: item.value,
                                key: item.key
                            })
                        }
                    } else {
                        ret.push({
                            value: item,
                            key: item
                        })
                    }
                })
                return ret;
            },
            fnComboSelect(n){
                n = n || 1;
                const self = this;
                let ccItem = false;
                let ccBaseKey = this.list[0].selected;
                let ccBase = this.comboBaseList;
                for(let count2 = 0;count2<n;count2++){
                    if(n && ccBase[this.list[count2].selected]){
                        ccBase = ccBase[this.list[count2].selected];
                        //ccBase
                    }
                }
                for(let count = n;count<Object.keys(this.list).length;count++){
                    if(ccBase.list) {
                        let ccData = self.fnFormat(ccBase.list)
                        let ccDefault = ccData[0] ? ccData[0].key : "";
                        if(self.valueKey && self.valueKey[n] && ccBase[self.valueKey[n]]){
                            ccDefault = self.valueKey[n];
                        }
                        this.list[count] = {
                            data: ccData,
                            length: ccData.length,
                            selected: ccDefault,
                            position: this.height * this.middleLength
                        }
                        ccBase = ccBase[ccDefault]
                    }
                }
            },
            fnCountMapList(arr){
                const self = this;
                let ret = {
                    list:[]
                };
                //计算映射
                arr.forEach(item=>{
                    let key = item.key;
                    if(item.children){
                        ret[key] = self.fnCountMapList(item.children);
                    }
                    ret.list.push({
                        key:item.key,
                        value:item.value
                    });
                })
                return ret;
            },
            //计算列表
            fnCountList(disChange) {
                if (isArray(this.columns)) {
                    let ret = {};
                    const self = this;
                    this.columnsNum = 0;

                    //处理一列数据
                    let deal = this.fnFormat;

                    this.isCombo = false;
                    if(this.columns[0].comboNum && this.columns[0].values){
                        this.isCombo = true;
                        let ccData =deal(this.columns[0].values)
                        self.comboBaseList = self.fnCountMapList(this.columns[0].values);
                        for(let counta = 0;counta < this.columns[0].comboNum ;counta++){
                            ret[counta] = {
                                label: self.columns[0].labels && self.columns[0].labels[counta] ? self.columns[0].labels[counta] : "",
                                style:self.columns[0].style && self.columns[0].style[counta] ? self.columns[0].style[counta] : {},
                            }
                        }
                        let ccDefault =  ccData[0] ? ccData[0].key : "";
                        if(self.valueKey && self.valueKey[0] && self.comboBaseList[self.valueKey[0]]){
                            ccDefault = self.valueKey[0];
                        }
                        ret[0] = {
                            data: ccData,
                            length: ccData.length,
                            selected:ccDefault,
                            position: this.height * this.middleLength
                        }
                    }

                    //多列
                    else if (this.columns[0] && this.columns[0].values) {

                        this.columns.forEach((item, key) => {
                            let ccKey = item.name || key;
                            let ccData = deal(item.values);
                            this.columnsNum++;
                            ret[ccKey] = {
                                data: ccData,
                                label: item.label,
                                style:item.style || {},
                                length: ccData.length,
                                selected: ccData[0] ? ccData[0].key : "",
                                position: this.height * this.middleLength
                            }
                            if (item.className) {
                                ret[ccKey].className = item.className;
                            }
                            if (item.defaultIndex) {
                                ret[ccKey].defaultIndex = item.defaultIndex;
                            }
                        })
                    }
                    //单列
                    else {
                        this.columnsNum++;
                        const ccData = deal(this.columns);
                        ret[0] = {
                            data: ccData,
                            length: ccData.length,
                            selected: ccData[0] ? ccData[0].key : "",
                            position: this.height * this.middleLength
                        }
                    }
                    !disChange && this.fnChange();
                    Vue.set(this, "list", ret);
                    if(this.isCombo){
                        self.fnComboSelect(1);
                    }

                }
            },
            //设置选中值
            fnSetSelect() {
                let ret = false;
                if (this.fnCheckValue(this.valueKey) && this.list[0]) {
                    ret = this.fnChooseByKey(0, this.valueKey, true);
                } else if (isObject(this.valueKey)) {
                    for (let column in this.list) {
                        //判断是是否为空
                        if (this.list.hasOwnProperty(column) && this.fnCheckValue(this.valueKey[column])) {
                            ret = this.fnChooseByKey(column, this.valueKey[column], true);
                        }
                    }
                }
                console.log("fnSetSelect",ret);
                return ret;
            },
            fnTouchStart(event, name) {
                this.duration = 0;
                this.startY[name] = event.touches[0].clientY;
                this.acceleration = this.acceleration || {};
                this.acceleration[name] = this.acceleration[name] || 0;
                this.minLength = -((this.list[name].length - this.middleLength) * this.height);
                this.maxLength =  this.height * (this.middleLength + 1);
            },
            fnTouchMove(event, name) {
                //console.log(event.preventDefault);
                event.preventDefault();
                const startY = event.touches[0].clientY;
                let position = range(this.list[name].position + startY - this.startY[name],  this.minLength,  this.maxLength);
                this.acceleration[name] = startY - this.startY[name];
                this.startY[name] = startY;
                this.list[name].position = position;
            },
            fnTouchEnd(event, name) {

                let position = this.list[name].position;
                let index = range(Math.round((this.height * this.middleLength - position) / this.height), 0, this.list[name].length - 1);
                this.duration = 200;
                if(this.acceleration[name] > 0 && position >= this.maxLength - this.height || this.acceleration[name] <0 && position <= this.minLength + this.height || this.acceleration[name] == 0){
                    this.fnChoose(name, index);
                }
                else{
                    const vt = this.acceleration[name]; //末速度
                    const acceleration = 40/150; //加速度
                    let inch = (vt*vt) / (2*acceleration); // 位移
                    if(vt<0){
                        inch = -inch;
                    }
                    let duration = Math.abs(vt/acceleration);
                    let ccStartPosition = position;
                    position = position + inch;
                    if(position >= this.maxLength - this.height ){
                        position = this.maxLength - this.height;
                        duration = Math.sqrt((inch - (position - ccStartPosition))/acceleration)
                    }
                    else if(position <= this.minLength + this.height){
                        position = this.minLength + this.height;
                        duration = Math.sqrt(Math.abs((inch - (position - ccStartPosition))/acceleration))
                    }
                    this.duration = duration * 10;
                    index = range(Math.round((this.height * this.middleLength - position) / this.height), 0, this.list[name].length - 1);
                    this.fnChoose(name, index);
                }
                //this.fnChoose(name, index);
            },
        },
        model: {
            prop: "valueKey",
            event: "update:valueKey"
        },
        props: {
            columns: Array,
            fontSize:"",
            checkColor:"",
            cursorClass: String,
            itemHeight: Number,
            itemSize: {
                default: "normal"
            },
            valueKey: "",
            visibleItemCount: {
                default: 5,
                type: Number
            }
        },
        watch: {
            valueKey() {
                this.fnSetSelect();
            },
            columns: {
                deep: true,
                handler() {
                    this.fnCountList();
                    this.fnSetSelect();
                }
            }
        },
        created() {
            this.fnCountList(true);
            //是否成功赋值
            let isSet = this.fnSetSelect();
            if (!isSet) {
                this.fnChange();
            }
        }
    }
</script>

<style lang="scss">
    @import "../css/var.scss";

    .y_picker {
        overflow: hidden;
        position: relative;
        font-size:$font_size_t3;
        display: flex;
    }

    .y_picker_cursor {
        display: flex;
        box-shadow: 0 0 2rem rgba(80, 7, 120, .05);
        top: 50%;
        left: 0;
        width: 100%;
        z-index: 1;
        position: absolute;
        pointer-events: none;
        -webkit-transform: translateY(-50%);
        transform: translateY(-50%);
    }

    .y_picker_label {
        flex: 1;
        text-align: right;
        color: $font_color_title;
    }

    .y_picker_column {
        padding: 0 5px;
        color: $font_color_contentSecondeary;
        text-align: center;
    }

    .y_picker_columnChecked {
        color: $color_topic_main;
        font-weight: bold;
    }

    .y_picker_box {
        flex: 1;
    }
</style>
