// Proto.js - 游戏协议处理
// 基于 proto/action.proto 和 proto/define.proto 生成

// 协议定义（将由本地 .proto 文件动态填充枚举值）
const GameProto = {};

// 协议编码器
class ProtoEncoder {
    constructor() {
        this.protobuf = window.protobuf;
        this.root = null;
        this.readyPromise = this.initProtobuf();
    }

    async initProtobuf() {
        try {
            // 使用本地 .proto 文件，避免硬编码
            const root = await this.protobuf.load([
                "proto/define.proto",
                "proto/action.proto"
            ]);
            this.root = root;
            // 缓存枚举，供其他模块使用
            this.MessageID = this.root.lookupEnum('MessageID').values;
            this.ActionID = this.root.lookupEnum('ActionID').values;

            // 更新全局GameProto枚举（避免硬编码）
            GameProto.MessageID = this.MessageID;
            GameProto.ActionID = this.ActionID;
            utils.info('Protobuf loaded from local files successfully');
        } catch (error) {
            utils.error('Failed to load protobuf files:', error);
        }
    }

    // 编码消息
    encodeMessage(messageId, payload) {
        try {
            if (!this.root) {
                throw new Error('Protobuf not initialized');
            }

            const Message = this.root.lookupType('Message');
            const message = {
                ID: messageId,
                Payload: payload
            };

            const buffer = Message.encode(message).finish();
            return buffer;
        } catch (error) {
            utils.error('Failed to encode message:', error);
            return null;
        }
    }

    // 编码动作
    encodeAction(actionId, payload) {
        try {
            if (!this.root) {
                throw new Error('Protobuf not initialized');
            }

            const C2S_Action = this.root.lookupType('C2S_Action');
            const action = {
                Action: actionId,
                Payload: payload
            };

            const buffer = C2S_Action.encode(action).finish();
            return buffer;
        } catch (error) {
            utils.error('Failed to encode action:', error);
            return null;
        }
    }

    // 解码消息
    decodeMessage(buffer) {
        try {
            if (!this.root) {
                throw new Error('Protobuf not initialized');
            }

            const Message = this.root.lookupType('Message');
            const message = Message.decode(buffer);
            return message;
        } catch (error) {
            utils.error('Failed to decode message:', error);
            return null;
        }
    }

    // 解码动作
    decodeAction(buffer) {
        try {
            if (!this.root) {
                throw new Error('Protobuf not initialized');
            }

            const C2S_Action = this.root.lookupType('C2S_Action');
            const action = C2S_Action.decode(buffer);
            return action;
        } catch (error) {
            utils.error('Failed to decode action:', error);
            return null;
        }
    }
}

// 协议工具类
class ProtoUtils {
    constructor() {
        this.encoder = new ProtoEncoder();
        this.readyPromise = this.encoder.readyPromise;
    }

    // 创建移动指令
    createMoveAction(x, y) {
        const moveData = new Uint8Array([x, y]);
        return this.encoder.encodeAction(this.encoder.ActionID.ACTION_ID_MOVE, moveData);
    }

    // 创建攻击指令
    createAttackAction(targetId) {
        const attackData = new Uint8Array([targetId]);
        return this.encoder.encodeAction(this.encoder.ActionID.ACTION_ID_ATTACK, attackData);
    }

    // 创建消息
    createMessage(messageId, payload) {
        return this.encoder.encodeMessage(messageId, payload);
    }

    // 解析接收到的数据
    parseReceivedData(data) {
        try {
            // 如果是字符串，尝试解析为JSON
            if (typeof data === 'string') {
                const jsonData = JSON.parse(data);
                return {
                    type: 'json',
                    data: jsonData
                };
            }

            // 如果是二进制数据，尝试解析为protobuf
            if (data instanceof ArrayBuffer || data instanceof Uint8Array) {
                const message = this.encoder.decodeMessage(data);
                return {
                    type: 'protobuf',
                    data: message
                };
            }

            return {
                type: 'unknown',
                data: data
            };
        } catch (error) {
            utils.error('Failed to parse received data:', error);
            return {
                type: 'error',
                data: null,
                error: error.message
            };
        }
    }

    // 验证坐标数据
    validateCoordinateData(data) {
        if (!Array.isArray(data) || data.length !== 2) {
            return false;
        }

        const [x, y] = data;
        return utils.validateCoordinates(x, y);
    }

    // 格式化坐标数据
    formatCoordinateData(data) {
        if (this.validateCoordinateData(data)) {
            const [x, y] = data;
            return {
                x: Math.round(x),
                y: Math.round(y),
                timestamp: Date.now()
            };
        }
        return null;
    }

    // 创建进入实例消息（外层Message）
    createEnterInstanceMessage(instanceId = 0) {
        try {
            if (!this.encoder.root) {
                utils.warn('Protobuf root not ready');
                return null;
            }
            const C2S_EnterInstance = this.encoder.root.lookupType('C2S_EnterInstance');
            const enterInstance = {
                InstanceID: instanceId
            };
            const innerBuffer = C2S_EnterInstance.encode(enterInstance).finish();
            return this.encoder.encodeMessage(
                this.encoder.MessageID.MESSAGE_ID_ENTER_INSTANCE,
                innerBuffer
            );
        } catch (error) {
            utils.error('Failed to create EnterInstance message:', error);
            return null;
        }
    }

    // 创建动作消息（外层Message）
    createActionMessage(actionId, x, y) {
        try {
            if (!this.encoder.root) {
                utils.warn('Protobuf root not ready');
                return null;
            }

            // 创建移动指令的payload
            let payload;
            if (actionId === this.encoder.ActionID.ACTION_ID_MOVE) {
                // 创建包含x,y坐标的二进制数据
                // 注意：这里使用Float64Array来存储双精度浮点数，因为proto中X和Y是double类型
                const buffer = new ArrayBuffer(16); // 8字节 * 2 = 16字节
                const view = new Float64Array(buffer);
                view[0] = x;
                view[1] = y;
                payload = new Uint8Array(buffer);
            } else {
                // 其他类型的动作可以在这里添加
                utils.warn('Unsupported action ID:', actionId);
                return null;
            }

            // 创建C2S_Action消息
            const C2S_Action = this.encoder.root.lookupType('C2S_Action');
            const action = {
                Action: actionId,
                Payload: payload
            };
            const actionBuffer = C2S_Action.encode(action).finish();

            // 封装到外层Message
            return this.encoder.encodeMessage(
                this.encoder.MessageID.MESSAGE_ID_ACTION,
                actionBuffer
            );
        } catch (error) {
            utils.error('Failed to create Action message:', error);
            return null;
        }
    }

    // 创建WASD方向动作消息（外层Message）
    createDirectionActionMessage(directionBits) {
        try {
            if (!this.encoder.root) {
                utils.warn('Protobuf root not ready');
                return null;
            }

            // 创建C2S_Action消息，payload为空
            const C2S_Action = this.encoder.root.lookupType('C2S_Action');
            const action = {
                Action: directionBits, // 使用位运算结果作为动作ID
                Payload: new Uint8Array(0) // 空payload
            };
            const actionBuffer = C2S_Action.encode(action).finish();

            // 封装到外层Message
            return this.encoder.encodeMessage(
                this.encoder.MessageID.MESSAGE_ID_ACTION,
                actionBuffer
            );
        } catch (error) {
            utils.error('Failed to create Direction Action message:', error);
            return null;
        }
    }
}

// 创建全局协议工具实例
const protoUtils = new ProtoUtils();

// 导出到全局
window.GameProto = GameProto;
window.ProtoEncoder = ProtoEncoder;
window.ProtoUtils = ProtoUtils;
window.protoUtils = protoUtils;

// 兼容性处理
if (typeof module !== 'undefined' && module.exports) {
    module.exports = {
        GameProto,
        ProtoEncoder,
        ProtoUtils,
        protoUtils
    };
} 