class ListViewAdapter {

    constructor(scrollView) {
        this.scrollView = scrollView;
        this.content = scrollView.content;
        this.scriptItems = [];
        this.dataList = [];
        // this.initialize();
        this.updateTimer = 0;
        this.updateInterval = 0.1;
        this.lastContentPosY = 0; // use this variable to detect if we are scrolling up or down
        this.spawnCount = 8;    //生成多少个预制资源
        this.itemHeight = 0;
        this.bufferZone = 500;
        this.spacing = 0;       //两个item之间的空隙
        this.scriptName = '';

        this.topHeight = 0;     //顶部空间
        this.shouldRemove = true;   //初始化前是否需要清除所有节点

        this.fuckingItem = null;
    }

    initialize(itemTemplate) {
        this.actualCount = this.dataList.length < this.spawnCount ? this.dataList.length : this.spawnCount;
        // let actualCount = this.dataList.length;
        this.scriptItems = [];
        if (this.itemHeight > 0) {
            this.content.height = (this.itemHeight + this.spacing) * this.dataList.length + this.topHeight;
        }
        if (this.shouldRemove) {
            this.content.removeAllChildren();
        }
        for (let i = 0; i < this.actualCount; ++i) { // spawn items, we only need to do this once
            let item = cc.instantiate(itemTemplate);
            if (this.itemHeight === 0) {
                this.itemHeight = item.height; // get total content height
                this.content.height = (this.itemHeight + this.spacing) * this.dataList.length + this.topHeight;
            }
            this.content.addChild(item);
            item.setPosition(0, -(item.height * (0.5 + i) + this.spacing * (i + 1) + this.topHeight));
            let itemScript = item.getComponent(this.scriptName);
            itemScript.setListViewAdapter(this);
            itemScript.updateItem(this.dataList[i], i, (newBuildingInfo) => {
                this.dataList[i] = newBuildingInfo;
            });
            this.scriptItems.push(itemScript);
            // console.log('content height: ', this.content.height);
        }
        this.bufferZone = (this.scrollView.node.height + this.itemHeight) / 2;

        //第一次数据加载完成后发出回调
        if (this.loadFinish != undefined) {
            this.loadFinish();
        }
    }

    getPositionInView(item) { // get item position in scrollview's node space
        let worldPos = item.parent.convertToWorldSpaceAR(item.position);
        let viewPos = this.scrollView.node.convertToNodeSpaceAR(worldPos);
        return viewPos;
    }

    update(dt) {
        // this.updateTimer += dt;
        // if (this.updateTimer < this.updateInterval) return; // we don't need to do the math every frame
        this.updateTimer = 0;
        let buffer = this.bufferZone;
        let isDown = this.content.y < this.lastContentPosY; // scrolling direction

        let offset = (this.itemHeight + this.spacing) * this.scriptItems.length;

        for (let i = 0; i < this.scriptItems.length; ++i) {
            let viewPos = this.getPositionInView(this.scriptItems[i].node);
            if (isDown) {
                // if away from buffer zone and not reaching top of content
                if (viewPos.y < -buffer && this.scriptItems[i].node.y + offset < 0) {
                    // this.scriptItems[i].node.setPositionY(this.scriptItems[i].node.y + offset);

                    let itemScript = this.scriptItems[i];
                    let itemId = itemScript._itemId - this.scriptItems.length;
                    if (itemId < 0) {
                        // this.scriptItems[i].node.active = false;
                        continue;
                    }

                    // this.scriptItems[i].node.active = true;
                    this.scriptItems[i].node.y = this.scriptItems[i].node.y + offset;
                    itemScript.updateItem(this.dataList[itemId], itemId, (newBuildingInfo) => {
                        this.dataList[itemId] = newBuildingInfo;
                    });
                }
            } else {
                // if away from buffer zone and not reaching bottom of content
                if (viewPos.y > buffer && this.scriptItems[i].node.y - offset > -this.content.height) {
                    // this.scriptItems[i].node.setPositionY(this.scriptItems[i].node.y - offset);

                    let itemScript = this.scriptItems[i];
                    let itemId = itemScript._itemId + this.scriptItems.length;
                    if (itemId >= this.dataList.length) {
                        // this.scriptItems[i].node.active = false;
                        continue;
                    }

                    // this.scriptItems[i].node.active = true;
                    this.scriptItems[i].node.y = this.scriptItems[i].node.y - offset;
                    itemScript.updateItem(this.dataList[itemId], itemId, (newBuildingInfo) => {
                        this.dataList[itemId] = newBuildingInfo;
                    });
                    if (itemId === (this.dataList.length - 1)) {
                        if (this.loadMore != undefined) {
                            this.loadMore();
                        }
                    }
                }
            }
        }
        // update lastContentPosY
        this.lastContentPosY = this.content.y;
    }

    updateItems(dataList, itemPrefab, scriptName, topHeight) {
        this.scriptName = scriptName;
        this.itemPrefab = itemPrefab;
        this.dataList = dataList;
        this.topHeight =  (topHeight === undefined) ? 0 : topHeight;
        this.initialize(itemPrefab);
    }

    //更新数据
    updateDataList(dataList, roomId) {
        this.dataList = dataList;

        for (let i = 0; i < this.scriptItems.length; ++i) {
            let itemScript = this.scriptItems[i];
            if (itemScript.data.roomId == roomId) {
                let itemId = itemScript._itemId;
                console.log('id id ' + roomId);
                itemScript.updateItem(itemScript.data, itemId, (newBuildingInfo) => {
                    this.dataList[itemId] = newBuildingInfo;
                });
            }
        }
    }

    //刷新已有数据
    refreshItems(dataList) {
        this.dataList = dataList;
        this.update();
    }

    addData(newdataList) {
        this.dataList = this.dataList.concat(newdataList);
        this.content.height = (this.itemHeight + this.spacing) * this.dataList.length; // get total content height
    }

    setLoadMoreCallBack(loadMore) {
        this.loadMore = loadMore;
    }

    setFirstLoadFinish(loadFinish) {
        this.loadFinish = loadFinish;
    }

    playRemoveItemAnimation(itemScript, animCallback) {
        this.dataList.splice(itemScript._itemId, 1);
        this.content.height = (this.itemHeight + this.spacing) * this.dataList.length; // get total content height

        let sequ = cc.sequence(cc.moveBy(0.2, -750, 0), animCallback);
        itemScript.node.runAction(sequ);
    }

    addItemsToDataList(model, head) {
        if (head) {
            this.dataList.unshift(model);
        } else {
            this.dataList.push(model);
        }

        this.actualCount = this.dataList.length < this.spawnCount ? this.dataList.length : this.spawnCount;
        //判断新的数据个数是否比设定的个数要大，不是的话就要创建新的item，是的话就直接复用已创建的
        if (this.dataList.length <= this.spawnCount) {
            let item = cc.instantiate(this.itemPrefab);
            this.content.height = (this.itemHeight + this.spacing) * this.dataList.length + this.topHeight;
            this.content.addChild(item);
            var i = 0;
            if (!head) {

            }

            item.setPosition(600, -(item.height * (0.5 + i) + this.spacing * (i + 1) + this.topHeight));
            let action = cc.moveBy(0.2,cc.v2(-600, 0));
            item.runAction(action);

            let itemScript = item.getComponent(this.scriptName);
            itemScript.setListViewAdapter(this);
            itemScript._itemId = 0;
            itemScript.updateItem(this.dataList[i], i, (newBuildingInfo) => {
                this.dataList[i] = newBuildingInfo;
            });
            this.scriptItems.unshift(itemScript);

            if (head) {
                for (let i = 1; i < this.actualCount; ++i) { // spawn items, we only need to do this once
                    let itemScript = this.scriptItems[i];
                    // this.scriptItems[i].node.y = -(this.itemHeight * (0.5 + i) + this.spacing * (i + 1) + this.topHeight);
                    let moveY = -(this.itemHeight * (0.5 + i) + this.spacing * (i + 1) + this.topHeight);
                    // let action = cc.moveTo(0.2,cc.v2(0, moveY));
                    // itemScript.node.runAction(action);
                    itemScript.node.y = moveY;
                    itemScript._itemId = i;
                }
            }
        } else {
            this.content.height = (this.itemHeight + this.spacing) * this.dataList.length + this.topHeight;

            //已生成足够多的预制资源，从底部抽取来使用
            if (head) {
                let last = this.scriptItems.length - 1;
                let itemScript = this.scriptItems[last];
                var index = 0;
                itemScript.updateItem(this.dataList[index], index, (newBuildingInfo) => {
                    this.dataList[index] = newBuildingInfo;
                });
                itemScript._itemId = 0;
                itemScript.node.y = -(this.itemHeight * (0.5 + index) + this.spacing * (index + 1) + this.topHeight);
                itemScript.node.x = 600;
                let action = cc.moveBy(0.2,cc.v2(-600, 0));
                itemScript.node.runAction(action);

                var temp = this.scriptItems[last];
                this.scriptItems.pop();
                this.scriptItems.unshift(temp);

                for (let i = 1; i < this.scriptItems.length; ++i) {
                    let itemScript = this.scriptItems[i];
                    let moveY = -(this.itemHeight * (0.5 + i) + this.spacing * (i + 1) + this.topHeight);
                    // let action = cc.moveTo(0.2,cc.v2(0, moveY));
                    // itemScript.node.runAction(action);
                    itemScript.node.y = moveY;
                    itemScript._itemId = i;
                }
            } else {

            }
        }
    }

    updateItemsAndDataList(dataList,itemScript) {
        this.dataList = dataList;

        let index = itemScript._itemId;
        let scriptItems = this.scriptItems;

        if (this.dataList.length >= scriptItems.length) {
            // itemScript.scheduleOnce(() => {
            //     itemScript.node.x = 0;
            // }, 0.2);

            for (let i = 0; i < scriptItems.length; ++i) {
                let itemNode = scriptItems[i].node;
                let script = scriptItems[i];
                let itemId = script._itemId;
                if (itemId < this.dataList.length) {
                    if (script._itemId > index) {
                        let finish = cc.callFunc(() => {
                            itemNode.y = itemNode.y - (this.itemHeight + this.spacing);
                            // script.updateItem(this.dataList[itemId], itemId);
                            script.updateItem(this.dataList[itemId], itemId, (newBuildingInfo) => {
                                this.dataList[itemId] = newBuildingInfo;
                            });
                        }, this);
                        let s = cc.sequence(cc.moveBy(0.2, 0, (this.itemHeight + this.spacing)), finish);
                        itemNode.runAction(s);
                    } else {
                        // itemScript.scheduleOnce(() => {
                            // script.updateItem(this.dataList[itemId], itemId);
                            script.updateItem(this.dataList[itemId], itemId, (newBuildingInfo) => {
                                this.dataList[itemId] = newBuildingInfo;
                            });
                        // }, 0.2);
                    }
                }
            }
        } else {

            for (let i = 0; i < scriptItems.length; ++i) {
                let itemId = scriptItems[i]._itemId;
                if (itemId === itemScript._itemId) {
                    this.scriptItems.splice(i, 1);
                }
            }

            for (let i = 0; i < scriptItems.length; ++i) {
                let itemNode = scriptItems[i].node;
                let script = scriptItems[i];
                if (script._itemId > index) {
                    let newId = script._itemId - 1;
                    itemNode.runAction(cc.moveBy(0.2, 0, (this.itemHeight + this.spacing)));
                    // script.updateItem(this.dataList[newId], newId);
                    script.updateItem(this.dataList[newId], newId, (newBuildingInfo) => {
                        this.dataList[itemId] = newBuildingInfo;
                    });
                }
            }

            itemScript.node.destroy();
        }
    }

    removeItem(itemScript) {
        let finish = cc.callFunc(() => {
            this.updateItemsAndDataList(itemScript);
        });
        this.playRemoveItemAnimation(itemScript, finish);
    }

    onDestroy() {
        this.scriptItems = [];
        this.content.removeAllChildren();
    }
}
module.exports = ListViewAdapter;
