text: /**
   * @file 同步组件
   * @author mengke01(kekee000@gmail.com)
   */
  
  
  define(
      function (require) {
          var i18n = require('../i18n/i18n');
          var Resolver = require('common/promise');
          var string = require('common/string');
          var project = require('./project');
          var program = require('./program');
          var resolvettf = require('./util/resolvettf');
          var font = require('fonteditor-core/ttf/font');
          var ttf2woff = require('fonteditor-core/ttf/ttf2woff');
          var ttf2eot = require('fonteditor-core/ttf/ttf2eot');
          var base642bytes = require('fonteditor-core/ttf/util/base642bytes');
          var loader = require('./loader');
          var SyncForm = require('./SyncForm');
          var syncStatus = require('./sync-status');
          var curSyncStatus = {};
          var DEFAULT_FONTTYPE = 'ttf'; // 同步默认的字体类型
          var exports = {};
  
          /**
           * 设置资源的同步能力
           *
           * @param {string} url 当前的同步资源
           * @param {number} status 状态
           */
          function setSyncStatus(url, status) {
              curSyncStatus[url] = (curSyncStatus[url] || 0xffff) & status;
              if (!status) {
                  delete curSyncStatus[url];
              }
          }
  
          /**
           * 获取资源同步能力
           * @param  {string} url 当前的同步资源
           * @return {number} 状态
           */
          function getSyncStatus(url) {
              return curSyncStatus[url] || 0;
          }
  
          /**
           * 检查同步状态，是否有新的记录
           *
           * @return {promise}
           */
          function checkSync(syncConfig) {
              var data = {
                  action: 'pull',
                  encode: 'base64',
                  fontName: syncConfig.name,
                  fontType: DEFAULT_FONTTYPE, // 暂时只接收ttf类型的字体
                  timestamp: syncConfig.timestamp || 0
              };
  
              var resolver = new Resolver();
              $.ajax({
                  url: syncConfig.url,
                  dataType: 'jsonp',
                  data: data
              }).then(function (data) {
                  if (data && data.status === 0) {
                      resolver.resolve(data.data);
                  }
                  // 有些服务器不支持拉取，这里也处理为有响应
                  else {
                      setSyncStatus(syncConfig.url, syncStatus.pullNoResponse);
                      resolver.resolve({
                          status: syncStatus.parseDataError
                      });
                  }
              }, function (reason) {
                  setSyncStatus(syncConfig.url, syncStatus.pullNoResponse);
                  // 不支持拉取，但有可能支持推送，这里也处理为成功
                  if (reason.status === 200) {
                      resolver.resolve({
                          status: syncStatus.pullNoResponse
                      });
                  }
                  else {
                      setSyncStatus(syncConfig.url, syncStatus.serviceNotAvailable);
                      resolver.reject({
                          status: syncStatus.serviceNotAvailable,
                          reason: 'sync no response'
                      });
                      alert(i18n.lang.msg_error_sync_font_address);
                  }
              });
              return resolver.promise();
          }
  
          /**
           * 检查是否带有更新的字体，有更新则解析
           *
           * @param  {Object} data 解析的数据
           * @return {promise}
           */
          function confirmSync(data) {
              var resolver = new Resolver();
              if (data.hasNew && (data.fontType === DEFAULT_FONTTYPE && data[data.fontType])) {
                  if (window.confirm(string.format(i18n.lang.msg_has_new_font_version, data.fontName))) {
                      // 解析后台传送过来的ttf字形
                      var ttfBuffer = new Int8Array(base642bytes(data[data.fontType])).buffer;
                      loader.load(ttfBuffer, {
                          type: data.fontType,
                          success: function (ttfObject) {
                              resolver.resolve({
                                  status: 0,
                                  hasNew: 1,
                                  newData: ttfObject,
                                  timestamp: data.timestamp
                              });
                          },
                          error: function () {
                              data.status = syncStatus.parseFontError;
                              resolver.reject(data);
                              alert(i18n.lang.msg_error_sync_font_version);
                          }
                      });
                  }
                  else {
                      data.status = syncStatus.cancelSync;
                      resolver.reject(data);
                  }
              }
              else {
                  data.status = syncStatus.noHasNew;
                  resolver.reject(data);
              }
              return resolver.promise();
          }
  
          /**
           * 根据配置获取需要同步的数据
           * @param  {Object} syncConfig 同步配置
           * @param  {Object} ttf        ttf对象
           * @return {Object}            同步的数据字段
           */
          function getSyncData(syncConfig, ttf) {
              var fontType = [];
              var syncData = {};
  
              if (syncConfig.woff || syncConfig.ttf || syncConfig.eot) {
                  ttf = resolvettf(ttf);
                  try {
                      var buffer = font.create(ttf).write({
                          type: 'ttf'
                      });
                  }
                  catch (e) {
                      program.fire('font-error', e);
                      alert(e.message);
                      throw e;
                  }
  
                  if (syncConfig.ttf) {
                      fontType.push('ttf');
                      syncData.ttf = font.toBase64(buffer);
                  }
  
                  if (syncConfig.woff) {
                      fontType.push('woff');
                      syncData.woff = font.toBase64(ttf2woff(buffer));
                  }
  
                  if (syncConfig.eot) {
                      fontType.push('eot');
                      syncData.eot = font.toBase64(ttf2eot(buffer));
                  }
  
                  buffer = null;
              }
  
              if (syncConfig.svg) {
                  fontType.push('svg');
                  var svg = font.create(ttf).write({
                      type: 'svg'
                  });
                  syncData.svg = font.toBase64(svg);
              }
  
              syncData.encode = 'base64';
              syncData.fontName = syncConfig.name;
              syncData.fontType = fontType.join(',');
              return syncData;
          }
  
          /**
           * 进行远程同步
           *
           * @param  {Object} syncConfig 同步配置
           * @param  {Object} ttf        ttf对象
           * @param  {Object} resolver   resolver对象
           */
          function doSync(syncConfig, ttf, resolver) {
              var form = new SyncForm(syncConfig.url, {
                  serviceStatus: getSyncStatus(syncConfig.url)
              });
              var syncData = getSyncData(syncConfig, ttf);
              form.submit(syncData).then(function (data) {
                  if (data.status === 0) {
                      resolver.resolve(data.data);
                  }
                  else {
                      data.status = syncStatus.parseDataError;
                      resolver.reject(data);
                  }
              }, function (data) {
                  // 推送无响应
                  if (data.status === syncStatus.pushNoResponse) {
                      setSyncStatus(syncConfig.url, syncStatus.pushNoResponse);
                  }
                  resolver.reject(data);
              });
          }
  
  
          /**
           * 进行远程推送服务
           *
           * @param  {Object} syncConfig 同步配置
           * @param  {Object} ttf        ttf对象
           * @param  {Object} resolver   resolver对象
           */
          function doPush(syncConfig, ttf, resolver) {
              if (!syncConfig.pushUrl) {
                  resolver.resolve({});
                  return;
              }
  
              var form = new SyncForm(syncConfig.pushUrl, {
                  serviceStatus: syncStatus.pushNoResponse // 推送服务不检查是否有返回
              });
              var syncData = getSyncData(syncConfig, ttf);
              form.submit(syncData).then(function (data) {
                  resolver.resolve(data);
              }, function (data) {
                  resolver.reject(data);
              });
          }
  
          /**
           * 更新推送时间戳，在下一次推送的时候发送时间戳
           *
           * @param  {string} projectId  项目编号
           * @param  {number} timestamp  当前记录时间戳
           * @param  {Object} syncConfig 同步配置
           */
          function updateSyncTimestamp(projectId, timestamp, syncConfig) {
              if (!syncConfig) {
                  syncConfig = project.getConfig(projectId).sync;
              }
              syncConfig.timestamp = timestamp || 0;
              project.updateConfig(projectId, {
                  sync: syncConfig
              });
          }
  
          /**
           * 添加一个任务
           *
           * @param {Object} options 任务参数
           * @param {string} options.type 同步类型，push or pull
           * @param {string} options.projectId 项目编号或者同步选项
           * @param {?Object} options.ttf 字体对象
           * @param {?Object} options.config 同步选项
           *
           * @return {Object} Promise对象
           */
          exports.addTask = function (options) {
              var syncType = options.type || 'push';
              var projectId = options.projectId;
              var ttf = options.ttf;
              var syncConfig = options.config;
              options = null;
  
              if (!syncConfig) {
                  syncConfig = project.getConfig(projectId).sync;
              }
  
              if (!syncConfig || (!syncConfig.url && !syncConfig.pushUrl)) {
                  return Resolver.rejected({
                      status: 2,
                      statusInfo: i18n.lang.msg_not_set_sync_info
                  });
              }
  
              var resolver = new Resolver();
              var promise = resolver.promise();
              // 仅设置推送地址，不设置同步地址则只进行推送
              if (syncType === 'push' && !syncConfig.url && syncConfig.pushUrl) {
                  doPush(syncConfig, ttf, resolver);
                  return promise;
              }
  
              if (syncType === 'pull') {
                  // 同步之后，如果有新纪录，则更新记录
                  checkSync(syncConfig).then(confirmSync).then(function (data) {
                      resolver.resolve(data);
                  }, function (data) {
                      resolver.reject(data);
                  });
              }
              else {
                  // 同步之后，如果有新纪录，则更新记录，不更新记录则进行推送
                  checkSync(syncConfig).then(confirmSync).then(function (data) {
                      resolver.resolve(data);
                  }, function (data) {
                      if (data.status === syncStatus.serviceNotAvailable) {
                          resolver.reject(data);
                          return;
                      }
  
                      // 获取当前推送的ttf，如果没有，则从本地存储中获取
                      if (!ttf) {
                          resolver.reject({
                              status: 2,
                              statusInfo: i18n.lang.msg_no_sync_font
                          });
                      }
                      else {
                          // 推送数据到同步服务器
                          doSync(syncConfig, ttf, resolver);
                          // 推送数据到推送地址
                          if(syncConfig.pushUrl && syncConfig.pushUrl !== syncConfig.url) {
                              setTimeout(function() {
                                  doPush(syncConfig, ttf, new Resolver());
                              }, 200);
                          }
                      }
                  });
              }
  
              // 更新当前的时间戳，这里包含两个来源，拉取新纪录的时间戳和推送成功后的时间戳
              promise.then(function (data) {
                  if (data && data.timestamp) {
                      updateSyncTimestamp(projectId, data.timestamp, syncConfig);
                  }
              });
  
              return promise;
          };
  
          return exports;
      }
  );
  