/**
 *
 */
package com.foc.push.service;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.foc.push.entity.PushConfigEntity;
import com.foc.push.entity.UserNotifyEntity;
import com.foc.push.entity.UserNotifyRecordEntity;
import com.foc.util.DBHandler;
import com.foc.util.DBHelper;
import com.foc.util.IdWorker;
import com.umeng.push.core.AndroidNotification;
import com.umeng.push.core.PushClient;
import com.umeng.push.android.AndroidCustomizedcast;
import com.umeng.push.android.AndroidUnicast;
import com.umeng.push.ios.IOSCustomizedcast;
import com.umeng.push.ios.IOSUnicast;

/**
 * 
 * @team IT Team
 * @author renmb
 * @version 1.0
 * @time  2016年12月10日
 */
public class PushService {

    private QueryRunner run = null;
    private PushClient client = new PushClient();
    
    public PushService(){
        try {
            this.run = new QueryRunner(DBHelper.getDataSource());
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     * 更加APPCODE获取配置信息
     * 
     * @author renmb
     * @time  2016年12月11日
     * @param appCode
     * @return
     */
    public PushConfigEntity getPushConfig(String appCode){
        try {
            StringBuffer buf = new StringBuffer();
            buf.append("SELECT * ");
            buf.append("  id, " );
            buf.append("  platform, " );
            buf.append("  app_code AS appCode, " );
            buf.append("  app_key AS appKey, " );
            buf.append("  app_name AS appName, " );
            buf.append("  app_token AS appToken, " );
            buf.append("  app_desc AS appDesc, " );
            buf.append("  is_production AS isProduction, " );
            buf.append("  status, " );
            buf.append("  created " );
            buf.append("FROM foc_push_config ");
            buf.append("WHERE app_code = '"+appCode+"' ");
            
            ResultSetHandler<List<PushConfigEntity>> handler = new BeanListHandler<PushConfigEntity>(PushConfigEntity.class);
            List<PushConfigEntity> list = this.run.query(buf.toString(), handler);

            if (list != null && list.size() > 0)
                return list.get(0);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return null;
    }
    /**
     * 更加用户ID获取TOEKN及应用配置信息
     * 
     * @author renmb
     * @time  2016年12月11日
     * @param userId
     * @return
     */
    public PushConfigEntity getPushConfigByUserId(String userId){
        try {
            StringBuffer buf = new StringBuffer();
            buf.append("SELECT c.id, " );
            buf.append("  c.platform, " );
            buf.append("  p.app_code AS appCode, " );
            buf.append("  c.app_key AS appKey, " );
            buf.append("  c.app_name AS appName, " );
            buf.append("  c.app_token AS appToken, " );
            buf.append("  c.app_desc AS appDesc, " );
            buf.append("  c.is_production AS isProduction, " );
            buf.append("  c.status, " );
            buf.append("  c.created, " );
            buf.append("  p.device_token  AS deviceToken " );
            buf.append("FROM sys_user_profiles p ");
            buf.append("LEFT JOIN foc_push_config c ");
            buf.append("  ON p.app_code=c.app_code ");
            buf.append("WHERE user_id='"+userId+"'");
//            System.out.println(buf.toString());
            ResultSetHandler<List<PushConfigEntity>> handler = new BeanListHandler<PushConfigEntity>(PushConfigEntity.class);
            List<PushConfigEntity> list = this.run.query(buf.toString(), handler);

            if (list != null && list.size() > 0)
                return list.get(0);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return null;
    }
    /**
     * 插入一条推送信息
     * 
     * @author renmb
     * @time  2016年12月11日
     * @param entity
     */
    public void addUserNotify(UserNotifyEntity entity){
        Map<String, Object> columnMap = new TreeMap<String, Object>();

        columnMap.put("id",      entity.getId());
        columnMap.put("type",    entity.getType());
        columnMap.put("title",   entity.getTitle());
        columnMap.put("content", entity.getContent());
        columnMap.put("extras",  entity.getExtras());
        columnMap.put("user_id", entity.getUserId());
        columnMap.put("item_id", entity.getItemId());
        
        columnMap.put("send_status",  entity.getSendStatus());
        columnMap.put("send_type",    entity.getSendType());
        columnMap.put("client_token", entity.getClientToken());
        columnMap.put("production_mode", entity.getProductionMode());// 推送日期
        columnMap.put("app_code",        entity.getAppCode());// 推送日期
        
        columnMap.put("create_date", entity.getCreateDate());// 推送日期
        
        List<Map<String, Object>> columnMapList = new ArrayList<Map<String, Object>>();
        columnMapList.add(columnMap);

        // 批量插入数据
        DBHandler dBHandler = new DBHandler();
        dBHandler.batchInsert("foc_user_notify", columnMapList);
        
        columnMap = new TreeMap<String, Object>();
        columnMap.put("id",        IdWorker.getNextId());
        columnMap.put("notify_id", entity.getId());
        columnMap.put("user_id",   entity.getUserId());
        columnMap.put("read_flag", "0");
        
        columnMapList = new ArrayList<Map<String, Object>>();
        columnMapList.add(columnMap);
        // 批量插入数据
//        DBHandler dBHandler = new DBHandler();
        dBHandler.batchInsert("foc_user_notify_record", columnMapList);
    }
    
    public void addUserNotifyRecord(UserNotifyRecordEntity entity){
        Map<String, Object> columnMap = new TreeMap<String, Object>();

        columnMap.put("id",        entity.getId());
        columnMap.put("notify_id", entity.getNotifyId());
        columnMap.put("user_id",   entity.getUserId());
        columnMap.put("read_flag", entity.getReadFlag());
        
        List<Map<String, Object>> columnMapList = new ArrayList<Map<String, Object>>();
        columnMapList.add(columnMap);

        // 批量插入数据
        DBHandler dBHandler = new DBHandler();
        dBHandler.batchInsert("foc_user_notify_record", columnMapList);
    }
    public void sendPush(String userId, String type, String title) {
        UserNotifyEntity notify = new UserNotifyEntity();
        notify.setId(IdWorker.getNextId());
        notify.setUserId(userId);// 消息接受者用户ID(*必填)
        notify.setType(type);// 消息类型(*必填)
        notify.setTitle(title);// 提示标题(*必填)
        
        this.sendPush(notify, null);
    }
    public void sendPush(String userId, String type, String title, Map<String, String> extras) {
        UserNotifyEntity notify = new UserNotifyEntity();
        notify.setId(IdWorker.getNextId());
        notify.setUserId(userId);// 消息接受者用户ID(*必填)
        notify.setType(type);// 消息类型(*必填)
        notify.setTitle(title);// 提示标题(*必填)
        
        this.sendPush(notify, extras);
    }
    /**
     * 向指定的用户发送推送信息
     * 
     * @author renmb
     * @time  2016年12月10日
     * @param notify
     * @param extras
     */
    public void sendPush(UserNotifyEntity notify, Map<String, String> extras) {
        notify.setSendStatus("FAILD");
        if(extras != null){// 
            
            notify.setExtras(JSON.toJSONString(extras));
        }
        PushConfigEntity config = this.getPushConfigByUserId(notify.getUserId());
        if(config != null ){// 有推送配置信息
            if(StringUtils.isNotEmpty(config.getAppKey())){
                if(StringUtils.isNotBlank(config.getDeviceToken())){// 已经收集用户的设备TOKEN，直接通过TOKEN推送
                    notify.setSendType("BY_TOKEN");// 通过设备TOKEN发送
                    notify.setClientToken(config.getDeviceToken());
                    if("Android".equals(config.getPlatform())){
                        
                        String errorCode = this.sendAndroidUnicast(config, notify, extras);
                        notify.setSendStatus(errorCode);
                    } else if("iOS".equals(config.getPlatform())){
                        
                        String errorCode = this.sendIOSUnicast(config, notify, extras);
                        notify.setSendStatus(errorCode);
                    }
                } else{// 根据绑定的用户TOKEN推送
                    notify.setSendType("BY_ALIAS");// 通过别名发送
                    notify.setClientToken(notify.getUserId());
                    if("Android".equals(config.getPlatform())){// Android手机
                        
                        String errorCode = this.sendAndroidCustomizedcast(config, notify, extras);
                        notify.setSendStatus(errorCode);
                    } else if("iOS".equals(config.getPlatform())){// iOS手机
                        
                        String errorCode = this.sendIOSCustomizedcast(config, notify, extras);
                        notify.setSendStatus(errorCode);
                    }
                }
            }
            notify.setAppCode(config.getAppCode());// APPCODE
            notify.setProductionMode(config.getIsProduction() ? "TRUE": "FALSE");// 推送模式
        }
        notify.setCreateDate(new Date());
        this.addUserNotify(notify);
    }
    public String sendAndroidUnicast(PushConfigEntity config, UserNotifyEntity notify, Map<String, String> extras) {
        try {
            AndroidUnicast unicast = new AndroidUnicast(config.getAppKey(), config.getAppToken());
            // TODO Set your device token
            unicast.setDeviceToken(config.getDeviceToken());
            unicast.setTicker(notify.getTitle());
            unicast.setTitle(notify.getTitle());
            unicast.setText(notify.getTitle());
            unicast.goAppAfterOpen();
            unicast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
            // TODO Set 'production_mode' to 'false' if it's a test device. 
            // For how to register a test device, please see the developer doc.
//            unicast.setProductionMode();
            if(config.getIsProduction()){// 生成模式
                
                unicast.setProductionMode();
            } else {// 开发调试模式
                
                unicast.setTestMode();
            }
            // Set customized fields
//            unicast.setExtraField("test", "helloworld");
            if(extras != null){
                for(String key:extras.keySet()){
                    
                    unicast.setExtraField(key, extras.get(key));
                }
            }
            unicast.setExtraField("type",     notify.getType());
            unicast.setExtraField("notifyId", notify.getId());
            return client.send(unicast);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return "FAILD";
    }
    public String sendIOSUnicast(PushConfigEntity config, UserNotifyEntity notify, Map<String, String> extras) {
        try {
            IOSUnicast unicast = new IOSUnicast(config.getAppKey(), config.getAppToken());
            // TODO Set your device token
            unicast.setDeviceToken(config.getDeviceToken());
            unicast.setAlert(notify.getTitle());
            unicast.setBadge( 0);
            unicast.setSound( "default");
            // TODO set 'production_mode' to 'true' if your app is under production mode
            if(config.getIsProduction()){// 生成模式
                
                unicast.setProductionMode();
            } else {// 开发调试模式
                
                unicast.setTestMode();
            }
//          unicast.setProductionMode();
            // Set customized fields
//            unicast.setCustomizedField("test", "helloworld");
            if(extras != null){
                for(String key:extras.keySet()){
                    
                    unicast.setCustomizedField(key, extras.get(key));
                }
            }
            unicast.setCustomizedField("type",     notify.getType());
            unicast.setCustomizedField("notifyId", notify.getId());
            return client.send(unicast);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return "FAILD";
    }
    public String sendAndroidCustomizedcast(PushConfigEntity config, UserNotifyEntity notify, Map<String, String> extras) {
        try {
            AndroidCustomizedcast customizedcast = new AndroidCustomizedcast(config.getAppKey(), config.getAppToken());
            // TODO Set your alias here, and use comma to split them if there are multiple alias.
            // And if you have many alias, you can also upload a file containing these alias, then 
            // use file_id to send customized notification.
            customizedcast.setAlias( notify.getUserId(), "USER_CODE");
            customizedcast.setTicker(notify.getTitle());
            customizedcast.setTitle( notify.getTitle() );
            customizedcast.setText(notify.getTitle());
            customizedcast.goAppAfterOpen();
            customizedcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
            if(extras != null){
                for(String key:extras.keySet()){
                    
                    customizedcast.setExtraField(key, extras.get(key));
                }
            }
            customizedcast.setExtraField("type",     notify.getType());
            customizedcast.setExtraField("notifyId", notify.getId());
            // TODO Set 'production_mode' to 'false' if it's a test device. 
            // For how to register a test device, please see the developer doc.
//            customizedcast.setProductionMode();
            if(config.getIsProduction()){// 生成模式
                
                customizedcast.setProductionMode();
            } else {// 开发调试模式
                
                customizedcast.setTestMode();
            }
            return client.send(customizedcast);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return "FAILD";
    }
    public String sendIOSCustomizedcast(PushConfigEntity config, UserNotifyEntity notify, Map<String, String> extras) {
        try {
            IOSCustomizedcast customizedcast = new IOSCustomizedcast(config.getAppKey(), config.getAppToken());
            // TODO Set your alias and alias_type here, and use comma to split them if there are multiple alias.
            // And if you have many alias, you can also upload a file containing these alias, then 
            // use file_id to send customized notification.
            customizedcast.setAlias( notify.getUserId(), "USER_CODE");
            customizedcast.setAlert( notify.getTitle() );
            customizedcast.setBadge( 0);
            customizedcast.setSound( "default");
            if(extras != null){
                for(String key:extras.keySet()){
                    
                    customizedcast.setCustomizedField(key, extras.get(key));
                }
            }
            customizedcast.setCustomizedField("type",     notify.getType());
            customizedcast.setCustomizedField("notifyId", notify.getId());
            // TODO set 'production_mode' to 'true' if your app is under production mode
//          customizedcast.setTestMode();
//          customizedcast.setProductionMode();
            if(config.getIsProduction()){// 生成模式
                
                customizedcast.setProductionMode();
            } else {// 开发调试模式
                
                customizedcast.setTestMode();
            }
            return client.send(customizedcast);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return "FAILD";
    }
    /**
     * 
     * @author renmb
     * @time  2016年12月10日
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub

        // 发送写扩展KEY-VALUE数据
        Map<String, String> extras = new HashMap<String, String>();
        extras.put("flightNo", "JD7824");
        extras.put("depIata",  "XIY");
        extras.put("arrIata",  "CKG");
        extras.put("flightDate", "2016-12-14");
        
//        UserNotifyEntity notify = new UserNotifyEntity();
//        notify.setId(IdWorker.getNextId());
//        notify.setUserId("793699551219298304");// 消息接受者用户ID(*必填)
//        notify.setType("MS1003");// 消息类型(*必填)
//        notify.setTitle("JD7824航班取消了、请小伙伴们关注。");// 提示标题(*必填)
        
        PushService service = new PushService();
//        service.sendPush(notify, extras);
        service.sendPush(args[0], "MS1003", "JD7824航班取消了、请小伙伴们关注。", extras);
    }

}
