// 地图工具函数 - 内联腾讯地图SDK核心代码

// 腾讯地图Key
const QQMAP_KEY = 'RO5BZ-ECZ63-7US3C-RT5QW-TIDZE-2FF35';

// 内联腾讯地图SDK核心代码
const QQMapWX = (function() {
  // 错误配置
  const ERROR_CONF = {
    KEY_ERR: 311,
    KEY_ERR_MSG: 'key格式错误',
    PARAM_ERR: 310,
    PARAM_ERR_MSG: '请求参数信息有误',
    SYSTEM_ERR: 600,
    SYSTEM_ERR_MSG: '系统错误',
    WX_ERR_CODE: 1000,
    WX_OK_CODE: 200
  };

  // API基础URL
  const BASE_URL = 'https://apis.map.qq.com/ws/';
  const URL_SEARCH = BASE_URL + 'place/v1/search';
  const URL_SUGGESTION = BASE_URL + 'place/v1/suggestion';
  const URL_GET_GEOCODER = BASE_URL + 'geocoder/v1/';
  const URL_DISTANCE = BASE_URL + 'distance/v1/';

  // 工具函数
  const Utils = {
    // 获取location参数
    getLocationParam(location) {
      if (typeof location == 'string') {
        const locationArr = location.split(',');
        if (locationArr.length === 2) {
          location = {
            latitude: location.split(',')[0],
            longitude: location.split(',')[1]
          };
        } else {
          location = {};
        }
      }
      return location;
    },

    // 验证location值
    checkLocation(param) {
      const location = this.getLocationParam(param.location);
      if (!location || !location.latitude || !location.longitude) {
        const errconf = this.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + ' location参数格式有误');
        param.fail(errconf);
        param.complete(errconf);
        return false;
      }
      return true;
    },

    // 构造错误数据结构
    buildErrorConfig(errCode, errMsg) {
      return {
        status: errCode,
        message: errMsg
      };
    },

    // 回调函数默认处理
    polyfillParam(param) {
      param.success = param.success || function () { };
      param.fail = param.fail || function () { };
      param.complete = param.complete || function () { };
    },

    // 处理用户参数是否传入坐标进行不同的处理
    locationProcess(param, locationsuccess, locationfail, locationcomplete) {
      const that = this;
      locationfail = locationfail || function (res) {
        res.statusCode = ERROR_CONF.WX_ERR_CODE;
        param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
      };
      locationcomplete = locationcomplete || function (res) {
        if (res.statusCode == ERROR_CONF.WX_ERR_CODE) {
          param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
        }
      };
      if (!param.location) {
        wx.getLocation({
          type: 'gcj02',
          success: locationsuccess,
          fail: locationfail,
          complete: locationcomplete
        });
      } else if (that.checkLocation(param)) {
        const location = Utils.getLocationParam(param.location);
        locationsuccess(location);
      }
    },

    // 构造微信请求参数
    buildWxRequestConfig(param, options, feature) {
      const that = this;
      options.header = { "content-type": "application/json" };
      options.method = 'GET';
      options.success = function (res) {
        const data = res.data;
        if (data.status === 0) {
          that.handleData(param, data, feature);
        } else {
          param.fail(data);
        }
      };
      options.fail = function (res) {
        res.statusCode = ERROR_CONF.WX_ERR_CODE;
        param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
      };
      options.complete = function (res) {
        const statusCode = +res.statusCode;
        switch(statusCode) {
          case ERROR_CONF.WX_ERR_CODE: {
            param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
            break;
          }
          case ERROR_CONF.WX_OK_CODE: {
            const data = res.data;
            if (data.status === 0) {
              param.complete(data);
            } else {
              param.complete(that.buildErrorConfig(data.status, data.message));
            }
            break;
          }
          default:{
            param.complete(that.buildErrorConfig(ERROR_CONF.SYSTEM_ERR, ERROR_CONF.SYSTEM_ERR_MSG));
          }
        }
      };
      return options;
    },

         // 数据处理函数
     handleData(param, data, feature) {
       if (feature == 'search') {
         const searchResult = data.data;
         const searchSimplify = [];
         for (let i = 0; i < searchResult.length; i++) {
           searchSimplify.push({
             id: searchResult[i].id || null,
             title: searchResult[i].title || null,
             latitude: searchResult[i].location && searchResult[i].location.lat || null,
             longitude: searchResult[i].location && searchResult[i].location.lng || null,
             address: searchResult[i].address || null,
             category: searchResult[i].category || null,
             tel: searchResult[i].tel || null,
             adcode: searchResult[i].ad_info && searchResult[i].ad_info.adcode || null,
             city: searchResult[i].ad_info && searchResult[i].ad_info.city || null,
             district: searchResult[i].ad_info && searchResult[i].ad_info.district || null,
             province: searchResult[i].ad_info && searchResult[i].ad_info.province || null
           });
         }
         param.success(data, {
           searchResult: searchResult,
           searchSimplify: searchSimplify
         });
       } else if (feature == 'suggest') {
         const suggestResult = data.data;
         const suggestSimplify = [];
         for (let i = 0; i < suggestResult.length; i++) {
           suggestSimplify.push({
             adcode: suggestResult[i].adcode || null,
             address: suggestResult[i].address || null,
             category: suggestResult[i].category || null,
             city: suggestResult[i].city || null,
             district: suggestResult[i].district || null,
             id: suggestResult[i].id || null,
             latitude: suggestResult[i].location && suggestResult[i].location.lat || null,
             longitude: suggestResult[i].location && suggestResult[i].location.lng || null,
             province: suggestResult[i].province || null,
             title: suggestResult[i].title || null,
             type: suggestResult[i].type || null
           });
         }
         param.success(data, {
           suggestResult: suggestResult,
           suggestSimplify: suggestSimplify
         });
       } else if (feature == 'reverseGeocoder') {
         const reverseGeocoderResult = data.result;
         const reverseGeocoderSimplify = {
           address: reverseGeocoderResult.address || null,
           latitude: reverseGeocoderResult.location && reverseGeocoderResult.location.lat || null,
           longitude: reverseGeocoderResult.location && reverseGeocoderResult.location.lng || null,
           adcode: reverseGeocoderResult.ad_info && reverseGeocoderResult.ad_info.adcode || null,
           city: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.city || null,
           district: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.district || null,
           nation: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.nation || null,
           province: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.province || null,
           street: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.street || null,
           street_number: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.street_number || null,
           recommend: reverseGeocoderResult.formatted_addresses && reverseGeocoderResult.formatted_addresses.recommend || null,
           rough: reverseGeocoderResult.formatted_addresses && reverseGeocoderResult.formatted_addresses.rough || null
         };
         param.success(data, {
           reverseGeocoderResult: reverseGeocoderResult,
           reverseGeocoderSimplify: reverseGeocoderSimplify
         });
       } else if (feature == 'calculateDistance') {
         const calculateDistanceResult = data.result.elements;  
         const distance = [];
         for (let i = 0; i < calculateDistanceResult.length; i++){
           distance.push(calculateDistanceResult[i].distance);
         }   
         param.success(data, {
           calculateDistanceResult: calculateDistanceResult,
           distance: distance
         });
       } else {
         param.success(data);
       }
     }
  };

  // QQMapWX类
  class QQMapWX {
    constructor(options) {
      if (!options.key) {
        throw Error('key值不能为空');
      }
      this.key = options.key;
    }

    // 逆地址解析
    reverseGeocoder(options) {
      const that = this;
      options = options || {};
      Utils.polyfillParam(options);
      
      const requestParam = {
        coord_type: options.coord_type || 5,
        get_poi: options.get_poi || 0,
        output: 'json',
        key: that.key
      };
      if (options.poi_options) {
        requestParam.poi_options = options.poi_options;
      }

      const locationsuccess = function (result) {
        requestParam.location = result.latitude + ',' + result.longitude;
        wx.request(Utils.buildWxRequestConfig(options, {
          url: URL_GET_GEOCODER,
          data: requestParam
        }, 'reverseGeocoder'));
      };
      Utils.locationProcess(options, locationsuccess);
    }

         // POI周边检索
     search(options) {
       const that = this;
       options = options || {};
       Utils.polyfillParam(options);

       if (!options.keyword) {
         const errconf = Utils.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + ' keyword参数格式有误');
         options.fail(errconf);
         options.complete(errconf);
         return;
       }

       const requestParam = {
         keyword: options.keyword,
         orderby: options.orderby || '_distance',
         page_size: options.page_size || 10,
         page_index: options.page_index || 1,
         output: 'json',
         key: that.key
       };

       if (options.address_format) {
         requestParam.address_format = options.address_format;
       }

       if (options.filter) {
         requestParam.filter = options.filter;
       }

       const distance = options.distance || "1000";
       const auto_extend = options.auto_extend || 1;

       const locationsuccess = function (result) {
         requestParam.boundary = "nearby(" + result.latitude + "," + result.longitude + "," + distance + "," + auto_extend + ")";
         wx.request(Utils.buildWxRequestConfig(options, {
           url: URL_SEARCH,
           data: requestParam
         }, 'search'));
       };

       Utils.locationProcess(options, locationsuccess);
     }

     // sug模糊检索
     getSuggestion(options) {
       const that = this;
       options = options || {};
       Utils.polyfillParam(options);

       if (!options.keyword) {
         const errconf = Utils.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + ' keyword参数格式有误');
         options.fail(errconf);
         options.complete(errconf);
         return;
       }

       const requestParam = {
         keyword: options.keyword,
         region: options.region || '全国',
         region_fix: options.region_fix || 0,
         policy: options.policy || 0,
         page_size: options.page_size || 10,
         page_index: options.page_index || 1,
         get_subpois: options.get_subpois || 0,
         output: 'json',
         key: that.key
       };

       if (options.address_format) {
         requestParam.address_format = options.address_format;
       }

       if (options.filter) {
         requestParam.filter = options.filter;
       }

       if (options.location) {
         const locationsuccess = function (result) {
           requestParam.location = result.latitude + ',' + result.longitude;
           wx.request(Utils.buildWxRequestConfig(options, {
             url: URL_SUGGESTION,
             data: requestParam
           }, "suggest"));
         };
         Utils.locationProcess(options, locationsuccess);
       } else {
         wx.request(Utils.buildWxRequestConfig(options, {
           url: URL_SUGGESTION,
           data: requestParam
         }, "suggest"));
       }
     }

     // 距离计算
     calculateDistance(options) {
       const that = this;
       options = options || {};
       Utils.polyfillParam(options);

       if (!options.to) {
         const errconf = Utils.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + ' to参数格式有误');
         options.fail(errconf);
         options.complete(errconf);
         return;
       }

       const requestParam = {
         mode: options.mode || 'walking',
         to: options.to,
         output: 'json',
         key: that.key
       };

       if (options.from) {
         options.location = options.from;
       }

       const locationsuccess = function (result) {
         requestParam.from = result.latitude + ',' + result.longitude;
         wx.request(Utils.buildWxRequestConfig(options, {
           url: URL_DISTANCE,
           data: requestParam
         }, 'calculateDistance'));
       };

       Utils.locationProcess(options, locationsuccess);
     }
  }

  return QQMapWX;
})();

// 全局QQMap实例
let qqmapInstance = null;

// 初始化腾讯地图SDK
function initQQMap() {
  if (!qqmapInstance) {
    try {
      qqmapInstance = new QQMapWX({
        key: QQMAP_KEY
      });
      console.log('腾讯地图SDK初始化成功');
    } catch (err) {
      console.error('初始化腾讯地图SDK失败:', err);
    }
  }
  return qqmapInstance;
}

// 获取腾讯地图SDK实例
function getQQMapInstance() {
  return qqmapInstance || initQQMap();
}

// 获取用户位置（使用微信的接口获取位置）
function getUserLocation() {
  return new Promise((resolve, reject) => {
    wx.getLocation({
      type: 'gcj02',
      success: (res) => {
        resolve({
          longitude: res.longitude,
          latitude: res.latitude
        });
      },
      fail: (error) => {
        console.error('获取位置失败:', error);
        reject(error);
      }
    });
  });
}

// 逆地理编码 - 根据经纬度获取地址信息
function getRegeo(longitude, latitude) {
  return new Promise((resolve, reject) => {
    const qqmap = getQQMapInstance();
    if (!qqmap) {
      reject({ success: false, message: '腾讯地图SDK未初始化' });
      return;
    }
    
    qqmap.reverseGeocoder({
      location: {
        latitude,
        longitude
      },
      success: (data, result) => {
        // 官方SDK返回的数据结构：data是原始数据，result是简化数据
        const reverseGeocoderSimplify = result.reverseGeocoderSimplify;
        resolve({
          success: true,
          data: {
            formatted_address: reverseGeocoderSimplify.address,
            addressComponent: {
              city: reverseGeocoderSimplify.city,
              district: reverseGeocoderSimplify.district,
              province: reverseGeocoderSimplify.province,
              street: reverseGeocoderSimplify.street,
              street_number: reverseGeocoderSimplify.street_number
            }
          }
        });
      },
      fail: (error) => {
        console.error('逆地理编码失败:', error);
        reject({ success: false, message: error.message || '逆地理编码失败' });
      }
    });
  });
}

// 搜索周边POI
function getPoiAround(longitude, latitude, keyword = '', radius = 1000) {
  return new Promise((resolve, reject) => {
    const qqmap = getQQMapInstance();
    if (!qqmap) {
      reject({ success: false, message: '腾讯地图SDK未初始化' });
      return;
    }
    
    qqmap.search({
      keyword: keyword,
      location: {
        latitude,
        longitude
      },
      distance: radius,
      success: (data, result) => {
        const searchSimplify = result.searchSimplify;
        resolve({
          success: true,
          data: searchSimplify
        });
      },
      fail: (error) => {
        console.error('搜索POI失败:', error);
        reject({ success: false, message: error.message || '搜索POI失败' });
      }
    });
  });
}

// 计算距离（异步）
function calculateDistance(from, to) {
  return new Promise((resolve, reject) => {
    const qqmap = getQQMapInstance();
    if (!qqmap) {
      reject({ success: false, message: '腾讯地图SDK未初始化' });
      return;
    }
    
    qqmap.calculateDistance({
      from: from,
      to: to,
      mode: 'walking',
      success: (data, result) => {
        const distance = result.distance;
        resolve({
          success: true,
          data: distance
        });
      },
      fail: (error) => {
        console.error('计算距离失败:', error);
        reject({ success: false, message: error.message || '计算距离失败' });
      }
    });
  });
}

// 计算距离（同步，使用球面距离公式）
function calculateDistanceSync(lat1, lng1, lat2, lng2) {
  const R = 6371000; // 地球半径（米）
  const dLat = (lat2 - lat1) * Math.PI / 180;
  const dLng = (lng2 - lng1) * Math.PI / 180;
  const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
    Math.sin(dLng / 2) * Math.sin(dLng / 2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  return Math.round(R * c); // 返回距离，单位为米
}

// 关键词提示
function getSuggestion(keyword, region = '全国') {
  return new Promise((resolve, reject) => {
    const qqmap = getQQMapInstance();
    if (!qqmap) {
      reject({ success: false, message: '腾讯地图SDK未初始化' });
      return;
    }
    
    qqmap.getSuggestion({
      keyword: keyword,
      region: region,
      success: (data, result) => {
        const suggestSimplify = result.suggestSimplify;
        resolve({
          success: true,
          data: suggestSimplify
        });
      },
      fail: (error) => {
        console.error('关键词提示失败:', error);
        reject({ success: false, message: error.message || '关键词提示失败' });
      }
    });
  });
}

// 导出函数
export {
  getUserLocation,
  getRegeo,
  getPoiAround,
  calculateDistance,
  calculateDistanceSync,
  getSuggestion,
  initQQMap,
  getQQMapInstance
};

// 测试距离计算函数（开发调试用）
export function testDistanceCalculation() {
  // 测试用例：北京天安门到故宫的距离（约1.5公里）
  const tiananmen = { lat: 39.908823, lng: 116.397470 };
  const gugong = { lat: 39.916527, lng: 116.397128 };
  
  const distance = calculateDistanceSync(tiananmen.lat, tiananmen.lng, gugong.lat, gugong.lng);
  console.log('天安门到故宫的距离:', distance, '米');
  console.log('转换为公里:', (distance / 1000).toFixed(2), '公里');
  
  return distance;
} 