#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Fins 模拟设备服务器
提供模拟的 Fins 设备用于测试在线脚本中的 Fins 内置函数
"""

import threading
import socket
import struct
import time

print("Fins 模拟设备服务器")


class MockFinsServer:
    """模拟 Fins 服务器用于测试"""
    
    def __init__(self, host='127.0.0.1', port=9600):
        self.host = host
        self.port = port
        self.server_socket = None
        self.running = False
        self.thread = None
        
        # 模拟数据存储
        self.memory_areas = {
            0x82: {  # DM 区域
                100: {  # 地址 100
                    'word': 1234,  # word 数据
                    'bits': [True, False, True, False, True, False, True, False],  # 8个位
                    'string': "HELLO WORLD"  # 字符串数据
                },
                200: {  # 地址 200
                    'word': 5678,
                    'bits': [False, True, False, True, False, True, False, True],
                    'string': "TEST DATA"
                }
            }
        }
    
    def start(self):
        """启动模拟服务器"""
        try:
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.server_socket.bind((self.host, self.port))
            self.server_socket.listen(5)
            self.running = True
            
            self.thread = threading.Thread(target=self._server_loop)
            self.thread.daemon = True
            self.thread.start()
            
            print(f"🟢 模拟 Fins 服务器已启动：{self.host}:{self.port}")
            print(f"📊 模拟数据:")
            print(f"   - 地址 100: word=1234, bits=[T,F,T,F,T,F,T,F], string='HELLO WORLD'")
            print(f"   - 地址 200: word=5678, bits=[F,T,F,T,F,T,F,T], string='TEST DATA'")
            time.sleep(0.1)  # 等待服务器完全启动
            
        except Exception as e:
            print(f"❌ 启动模拟 Fins 服务器失败: {str(e)}")
            raise
    
    def stop(self):
        """停止模拟服务器"""
        self.running = False
        if self.server_socket:
            self.server_socket.close()
        if self.thread:
            self.thread.join(timeout=1.0)
        print("🔴 模拟 Fins 服务器已停止")
    
    def _server_loop(self):
        """服务器主循环"""
        while self.running:
            try:
                client_socket, addr = self.server_socket.accept()
                print(f"📞 客户端连接: {addr}")
                
                # 处理客户端请求
                self._handle_client(client_socket)
                
            except Exception as e:
                if self.running:
                    print(f"❌ 服务器循环错误: {str(e)}")
                break
    
    def _handle_client(self, client_socket):
        """处理客户端请求"""
        try:
            # 接收请求
            data = client_socket.recv(1024)
            if not data:
                return
            
            print(f"📨 收到请求数据: {data.hex()}")
            
            # 解析并响应
            response = self._process_fins_request(data)
            
            if response:
                client_socket.send(response)
                print(f"📤 发送响应数据: {response.hex()}")
            
        except Exception as e:
            print(f"❌ 处理客户端请求失败: {str(e)}")
        finally:
            client_socket.close()
    
    def _process_fins_request(self, request_data):
        """处理 Fins 请求并生成响应"""
        try:
            # 简化的 Fins 协议解析
            if len(request_data) < 28:
                return None
            
            # 跳过 TCP 头部，解析 Fins 命令
            fins_start = 16  # 跳过 FINS TCP 头部
            
            # 提取命令码
            cmd = struct.unpack('>H', request_data[fins_start + 10:fins_start + 12])[0]
            area = request_data[fins_start + 12]
            addr_high = request_data[fins_start + 13]
            addr_low = request_data[fins_start + 14]
            bit_offset = request_data[fins_start + 15]
            
            address = (addr_high << 8) | addr_low
            
            print(f"🔍 解析命令: CMD=0x{cmd:04X}, Area=0x{area:02X}, Addr={address}, Bit={bit_offset}")
            
            # 生成响应
            if cmd == 0x0101:  # 读取命令
                return self._create_read_response(area, address, bit_offset, request_data)
            elif cmd == 0x0102:  # 写入命令
                return self._create_write_response(area, address, bit_offset, request_data)
            
        except Exception as e:
            print(f"❌ 处理 Fins 请求失败: {str(e)}")
            return None
    
    def _create_read_response(self, area, address, bit_offset, request_data):
        """创建读取响应"""
        try:
            # 构造响应头部
            response_header = b'FINS' + b'\x00' * 12
            
            # Fins 响应头部（复制请求头部并修改）
            fins_header = request_data[16:26]  # 复制原始头部
            
            # 添加响应码 (成功)
            response_code = struct.pack('>H', 0x0000)
            
            # 获取模拟数据
            if area in self.memory_areas and address in self.memory_areas[area]:
                area_data = self.memory_areas[area][address]
                
                # 根据请求类型返回不同数据
                if bit_offset == 0:  # Word 读取
                    word_data = struct.pack('>H', area_data['word'])
                    data_part = word_data
                else:  # Bit 读取
                    bit_value = 1 if area_data['bits'][bit_offset] else 0
                    data_part = struct.pack('B', bit_value)
            else:
                # 返回默认数据
                data_part = b'\x00\x00'
            
            # 组装完整响应
            fins_response = fins_header + response_code + data_part
            
            # 更新长度
            length = len(fins_response)
            response_header = response_header[:8] + struct.pack('>I', length) + response_header[12:]
            
            return response_header + fins_response
            
        except Exception as e:
            print(f"❌ 创建读取响应失败: {str(e)}")
            return None
    
    def _create_write_response(self, area, address, bit_offset, request_data):
        """创建写入响应"""
        try:
            # 模拟写入操作
            print(f"✏️ 模拟写入: Area=0x{area:02X}, Addr={address}, Bit={bit_offset}")
            
            # 构造简单的成功响应
            response_header = b'FINS' + b'\x00' * 12
            fins_header = request_data[16:26]
            response_code = struct.pack('>H', 0x0000)  # 成功
            
            fins_response = fins_header + response_code
            
            # 更新长度
            length = len(fins_response)
            response_header = response_header[:8] + struct.pack('>I', length) + response_header[12:]
            
            return response_header + fins_response
            
        except Exception as e:
            print(f"❌ 创建写入响应失败: {str(e)}")
            return None


def start_mock_fins_server():
    """启动模拟 Fins 服务器"""
    server = MockFinsServer('127.0.0.1', 9600)
    server.start()
    return server


if __name__ == "__main__":
    print("🚀 启动 Fins 模拟设备服务器")
    print("=" * 50)
    
    try:
        # 启动模拟服务器
        server = start_mock_fins_server()
        
        print("\n📋 测试说明:")
        print("  可以在在线脚本中使用以下代码测试:")
        print("")
        print("  # 测试读取 word")
        print("  result = VWED.fins.read_fins_word('127.0.0.1', 9600, 0x82, 100, 0)")
        print("  print(f'读取 word 结果: {result}')  # 期望: 1234")
        print("")
        print("  # 测试读取 bit")
        print("  result = VWED.fins.read_fins_bit('127.0.0.1', 9600, 0x82, 100, 0)")
        print("  print(f'读取 bit 结果: {result}')  # 期望: 1 (True)")
        print("")
        print("  # 测试写入 word")
        print("  VWED.fins.write_fins_word('127.0.0.1', 9600, 0x82, 200, 0, 9999)")
        print("  print('写入 word 完成')")
        print("")
        print("  # 测试写入 bit")
        print("  VWED.fins.write_fins_bit('127.0.0.1', 9600, 0x82, 200, 3, True)")
        print("  print('写入 bit 完成')")
        print("")
        print("💡 按 Ctrl+C 停止服务器")
        
        # 保持服务器运行
        while True:
            time.sleep(1)
            
    except KeyboardInterrupt:
        print("\n⏹️ 收到停止信号")
    except Exception as e:
        print(f"\n❌ 服务器运行失败: {str(e)}")
    finally:
        if 'server' in locals():
            server.stop()
        print("👋 再见!")