import os
from flask import Flask, send_file, abort, Response, url_for
import folium
from folium import plugins
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import json
import time
import re
from threading import Thread, Lock

# Flask 服务
app = Flask(__name__, static_folder='static')
tile_dir = os.path.join(os.path.dirname(__file__), "tiles")
kml_dir = os.path.join(os.path.dirname(__file__), "kml")  # KML文件目录

# 确保KML目录存在
os.makedirs(kml_dir, exist_ok=True)

# 用于存储文件变化事件的队列
file_changes = []
changes_lock = Lock()

def extract_tile_coords(filepath):
    """从文件路径中提取瓦片坐标信息"""
    # 匹配形如 tiles/19/123_456.png 的路径
    pattern = r'tiles/(\d+)/(\d+)_(\d+)\.png$'
    match = re.search(pattern, filepath)
    if match:
        z = int(match.group(1))
        x = int(match.group(2))
        y = int(match.group(3))
        return {'z': z, 'x': x, 'y': y}
    return None

class TileHandler(FileSystemEventHandler):
    def on_any_event(self, event):
        if event.is_directory:
            return
        if event.src_path.endswith('.png'):
            coords = extract_tile_coords(event.src_path)
            if coords:
                with changes_lock:
                    file_changes.append({
                        'coords': coords,
                        'time': time.time()
                    })
                    # 只保留最近100个变化
                    if len(file_changes) > 100:
                        file_changes.pop(0)

# 启动文件监控
observer = Observer()
observer.schedule(TileHandler(), tile_dir, recursive=True)
observer.start()

@app.route('/tiles/<int:z>/<x_y>.png')
def serve_tile(z, x_y):
    """提供瓦片图片服务"""
    print(f"请求瓦片：层级={z}, 文件名={x_y}.png")
    filename = f"{x_y}.png"
    filepath = os.path.join(tile_dir, str(z), filename)
    if os.path.exists(filepath):
        return send_file(filepath)
    else:
        abort(404)

@app.route('/check_changes')
def check_changes():
    """检查文件变化"""
    with changes_lock:
        changes = file_changes.copy()
        file_changes.clear()
    return json.dumps(changes)



@app.route('/kml/<filename>')
def serve_kml(filename):
    """提供KML文件服务"""
    filepath = os.path.join(kml_dir, filename)
    if os.path.exists(filepath):
        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                kml_content = f.read()
            return Response(kml_content, mimetype='application/vnd.google-earth.kml+xml')
        except Exception as e:
            print(f"处理KML文件 {filename} 时出错: {str(e)}")
            abort(500)
    else:
        abort(404)


@app.route('/')
def index():
    """显示地图页面"""
    # 创建地图
    m = folium.Map(
        location=[30.253729, 114.453506],  # 武汉市中心坐标
        zoom_start=19,
        min_zoom=1,
        max_zoom=23,
        tiles=None,  # 禁用默认图层
        control_scale=True  # 显示比例尺
    )
    
    # 添加在线瓦片图层
    folium.TileLayer(
        tiles='https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',
        attr='Google Maps',
        name='谷歌地图',
        min_zoom=1,
        max_zoom=20,
    ).add_to(m)

    # folium.TileLayer(
    #     tiles='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
    #     attr='OpenStreetMap',
    #     name='OpenStreetMap',
    #     min_zoom=1,
    #     max_zoom=19,
    # ).add_to(m)

    # folium.TileLayer(
    #     tiles='https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
    #     attr='OpenTopoMap',
    #     name='OpenTopoMap',
    #     min_zoom=1,
    #     max_zoom=17,
    # ).add_to(m)
    
    # 添加自定义瓦片层
    folium.TileLayer(
        tiles='http://localhost:5000/tiles/{z}/{x}_{y}.png',
        attr='高德瓦片服务',
        min_zoom=1,
        max_zoom=23,
        maxNativeZoom=19,
        minNativeZoom=19,
        name='本地瓦片',
    ).add_to(m)
    
    # 添加KML文件
    # kml_files = [f for f in os.listdir(kml_dir) if f.endswith('.kml')]
    # for kml_file in kml_files:
    #     kml_url = url_for('serve_kml', filename=kml_file)
    #     try:
            
    #         plugins.Kml(
    #             kml_url,
    #             name=kml_file,
    #             show=True,
    #             overlay=True
    #         ).add_to(m)
    #     except Exception as e:
    #         print(f"加载KML文件 {kml_file} 时出错: {str(e)}")
    
    # 添加控件
    plugins.Fullscreen().add_to(m)  # 全屏控件
    plugins.MousePosition().add_to(m)  # 鼠标位置显示
    folium.LayerControl().add_to(m)  # 添加图层控制

    # 添加自定义JavaScript
    m.get_root().html.add_child(folium.Element(f"""
        <script src="{url_for('static', filename='js/tile-updater.js')}"></script>
        <script>
            document.addEventListener('DOMContentLoaded', function() {{
                // 初始化瓦片更新器
                new TileUpdater(map);
            }});
        </script>
    """))
    
    # 返回地图HTML
    return m._repr_html_()

if __name__ == "__main__":
    try:
        app.run(port=5000, debug=True)
    finally:
        observer.stop()
        observer.join()
