Source: protocol/data.js

/**
 * Mobizen - Mobizen/Socket/Channel/Data
 *
 * IMPORTANT NOTE: This file is licensed only for use in providing the RSUPPORT services,
 *
 * @copyright 2015 RSUPPORT CO., LTD. All rights reserved.
 * @license Dedicated to the public domain.
 * @author Joon Kyoung <firejune@gmail.com>
 *
 */

(function(exports) {
  "use strict";

  /** @typedef {Mobizen} */
  var Mobizen = exports.Mobizen || (exports.Mobizen = {});

  /**
   * @constructs Data
   * @memberof Mobizen.Socket.Channel
   * @extends Mobizen.Socket.Channel
   * @param {Mobizen.Socket} socket - A provider of Mobizen/Socket API.
   *
   */
  function Data(socket) {
    this.super_.call(this, socket, 'data');
    /** @typedef {Mobizen.Socket#specific} */
    this.specific = socket.specific;
  }

  Mobizen.Inherits(Data, Mobizen.Channel, /** @lends Mobizen.Socket.Channel.Data# */ {
    /**
     * @fires Mobizen#connected
     */
    start: function() {
      //console.log('Data.start');

      if (this.started) {
        return console.error('already started');
      }

      // open tcp channel for gateway
      if (this.socket.type == 'www') {
        this.send('listen.' + 10, {
          channelId: 10,
          guid: this.socket.params.instantId
        });
      }

      /**
       * @event Mobizen#connected
       * @type {Mobizen.Event}
       */
      this.socket.m.emit('connected');
      /** @type {boolean} */
      this.started = true;
    },

    /**
     * @param {string} cmd
     * @param {object} data
     * @return {object} data of struct
     * @exception Will throw an error if unknown command
     * @todo TBD: 메시지 이름과 이벤트 이름을 통일
     */
    send: function(cmd, data) {
      var topic;

      if (cmd.match('listen.')) {
        cmd = 'listen.*';
      }

      switch(cmd) {
        // 200-0 Request listen channel
        case 'listen.*': topic = 'Channel-ListenRequest'; break;
        // 200-8 Request connection close
        case 'close': topic = 'Channel-ConnectClose'; break;
        // 200-11 Request stop listen channel
        case 'stop': topic = 'Channel-StopListenRequest'; break;

        // 204-0 Send open draw process
        case 'draw.open': topic = 'Draw-Open'; break;
        // 204-1 Send terminate draw process
        case 'draw.close': topic = 'Draw-Close'; break;
        // 204-2 Send draw start data
        case 'draw.start': topic = 'Draw-Start'; break;
        // 204-3 Send drawing data
        case 'draw.data': topic = 'Draw-Data'; break;
        // 204-7 Send clear screen
        case 'draw.clear': topic = 'Draw-Clear'; break;
        // 204-100 Send draw end
        case 'draw.end': topic = 'Draw-End'; break;

        // 208-0 Request process list (DEMON)
        case 'process': topic = 'Process-Observe'; break;
        // 208-4 Send process kill
        case 'process.kill': topic = 'Process-KillSend'; break;
        // 208-6 Send process run
        case 'process.run': topic = 'Process-RunSend'; break;
        // 208-7 Send close all running processes
        case 'process.allkill': topic = 'Process-CloseAllSend'; break;

        // 209-0 Request file list
        case 'files': topic = 'File-Path'; break;
        // 209-3 Request delete file
        case 'file.delete': topic = 'File-DeleteRequest'; break;
        // 209-5 Request change file name
        case 'file.rename': topic = 'File-RenameRequest'; break;
        // 209-7 Request create a new folder
        case 'file.create': topic = 'File-MakeFolderRequest'; break;
        // 209-12 Send find file start
        case 'file.find': topic = 'File-Find'; break;
        // 209-51 Request cancel find file
        case 'file.find.cancel': topic = 'File-Stop'; break;
        // 209-101 Send file copy/move start
        case 'file.copymove': topic = 'File-CopyMoveRequest'; break;
        // 209-107 Send cancel of file tasks
        case 'file.cancel': topic = 'File-CancelRequest'; break;

        // 220-0 Response viewer info
        case 'viewer': topic = 'Remote-ViewerInfo'; break;
        // 220-71 Request login info
        case 'login.local':
        case 'login.browser': topic = 'Remote-HttpLoginIdRequest'; break;

        // 232-0 Request toggle screen recording
        case 'record': topic = 'Record-ToggleRequest'; break;

        // 234-1 Request input text paste to device
        case 'input.paste': topic = 'Input-PasteRequest'; break;
        // 234-3 Request soft keyboard enable status
        case 'input.status': topic = 'Input-StatusRequest'; break;
        // 234-4 Send soft keyboard select
        case 'input.toggle': topic = 'Input-SelectSend'; break;

        // 235-7 Request start screen on/off signal (DEMON)
        case 'notify.screen': topic = 'Notify-ConnectionStarted'; break;

        // 236-0 Request device info
        case 'device': topic = 'Device-InfoRequest'; break;
        // 236-2 Request wake up
        case 'wakeup': topic = 'Device-Wake'; break;
        // 236-3 Request desk size
        case 'disksize': topic = 'Device-DiskSizeRequest'; break;
        // 236-11 Request sd card info
        case 'sdcard': topic = 'Device-SDCardInfoRequest'; break;
        // 236-17 Request software button visible
        case 'device.button': topic = 'Device-HWNavigation'; break;
        // 236-19 Send display apk update for inject permession
        case 'device.update': topic = 'Device-APKInstall'; break;

        // 237-0 Send backup start
        case 'backup.start': topic = 'Archive-BackupRequest'; break;
        // 237-10 Send restore cancel
        case 'restore.cancel': topic = 'Archive-Cancel'; break;
        // 237-16 Send restore option
        case 'restore.option': topic = 'Archive-Option'; break;
        // 237-30 Send backup info
        case 'backup.info': topic = 'Archive-FolderInfoRequest'; break;
        // 237-200 Send backup end
        case 'backup.end': topic = 'Archive-Terminate'; break;

        // 242-0 Request media files
        case 'media.photos':
        case 'media.videos':
        case 'media.music': topic = 'Media-DataRequest'; this.listener = cmd; break;
        // 242-4 Request preview image of media
        case 'media.thumbnail': topic = 'Media-PreviewRequest'; break;
        // 242-6 Send indexing cancel
        case 'media.cancel': topic = 'Media-Cancel'; break;
        // 242-7 Send indexing pause
        case 'media.pause': topic = 'Media-Pause'; break;
        // 242-8 Send indexing resume
        case 'media.resume': topic = 'Media-Resume'; break;
        // 242-30 Request database sync
        case 'media.sync': topic = 'Media-Sync'; break;
        // 242-100 Request media search
        case 'media.search': topic = 'Media-SingleDataRequest'; break;
        // 242-102 Request media access
        case 'media.access': topic = 'Media-Access'; break;

        // 243-0 Request call logs total count
        case 'calllog': topic = 'CallLog-TotalCountRequest'; break;
        // 243-20 Request call all logs
        case 'calllog.all': topic = 'CallLog-All'; break;
        // 243-30,31 Request call logs delete
        case 'calllog.delete': topic = 'CallLog-' + (!data ? 'DeleteAll' : 'DeleteRequest'); break;

        // 244-0 Request contact total count
        case 'contacts': topic = 'Contact-TotalCountRequest'; break;
        // 244-5 Request contact request canel
        case 'contact.cancel': topic = 'Contact-Cancel'; break;
        // 244-10 Request delete contact
        case 'contact.delete': topic = 'Contact-DeleteRequest'; break;
        // 244-20 Request contact create
        case 'contact.create': topic = 'Contact-CreateRequest'; break;
        // 244-30 Request contact aggregation
        case 'contact.aggregation': topic = 'Contact-AggregationRequest'; break;
        // 244-40 Request contact insert field
        case 'contact.insert.field': topic = 'Contact-NewFieldRequest'; break;
        // 244-50 Request contact delete field
        case 'contact.delete.field': topic = 'Contact-RemoveFieldRequest'; break;
        // 244-60 Request contact update field
        case 'contact.update.field': topic = 'Contact-UpdateFieldRequest'; break;
        // 244-70 Request contact groups
        case 'contact.groups': topic = 'Contact-GroupRequest'; break;
        // 244-72 Request a contact
        case 'contact': topic = 'Contact-DataRequest'; break;
        // 244-80 Request all contacts
        case 'contacts.all': topic = 'Contact-All'; break;
        // 244-83 Request contact request pause
        case 'contact.pause': topic = 'Contact-Pause'; break;
        // 244-84 Request contact request resume
        case 'contact.resume': topic = 'Contact-Resume'; break;
        // 244-85 Request contactData by id
        case 'contact.single': topic = 'Contact-SingleContactRequest'; break;
        // 244-90 Request contact avatar
        case 'contact.avatar': topic = 'Contact-AvatarRequest'; break;
        // 244-92 Request contactId by phone number
        case 'contact.id': topic = 'Contact-ContactIdRequest'; break;

        // 245-0 Request contacts
        case 'message.contacts': topic = 'SMS-ContactsRequest'; break;
        // 245-2 Request messages
        case 'message.conversation': topic = 'SMS-ConversationRequest'; break;
        // 245-4 Request send message
        case 'message.send': topic = 'SMS-MessageSendRequest'; break;
        // 245-6 Request delete message
        case 'message.delete': topic = 'SMS-MessageDeleteRequest'; break;
        // 245-8 Request search message
        case 'message.search': topic = 'SMS-SearchRequest'; break;
        // 245-10 Request delete message
        case 'message.contact.delete': topic = 'SMS-ContactDeleteRequest'; break;

        // 246-0 Request phone call
        case 'dial': topic = 'Share-PhoneCall'; break;
        // 246-10 Request share app list
        case 'share.apps': topic = 'Share-AppInfo'; break;
        // 246-14 Request content share
        case 'share.contents': topic = 'Share-ContentShareRequest'; break;

        // 249-10 Request device location
        case 'finddevice.location': topic = 'FindDevice-LocationRequest'; break;
        // 249-20 Request tracking interval setting
        case 'finddevice.track': topic = 'FindDevice-TrackRequest'; break;
        // 249-22 Send track interval config to mobile
        case 'finddevice.trackconfig': topic = 'FindDevice-SetTrackConfig'; break;
        // 249-30 Request ring
        case 'finddevice.ring': topic = 'FindDevice-RingRequest'; break;
        // 249-32 Request ring
        case 'finddevice.ringstatus': topic = 'FindDevice-RingStatusRequest'; break;
        // 249-40 Request lock screen
        case 'finddevice.lockscreen': topic = 'FindDevice-LockScreenRequest'; break;
        // 249-50 Request reset phone
        case 'finddevice.resetphone': topic = 'FindDevice-ResetPhoneRequest'; break;
        // 249-60 Push GPS config
        case 'finddevice.pushgps': topic = 'FindDevice-PushGPS'; break;
        // 249-61 Push lock, reset config
        case 'finddevice.pushlockreset': topic = 'FindDevice-PushLockReset'; break;
      }

      //console.debug('capitalize command', capitalize(cmd));

      if (topic !== undefined) {
        topic = topic.split('-');
        return this.protocol.request(this.name, topic[0], topic[1], data);
      } else {
        return new Error('Unknown command:', cmd);
      }
    },

    /**
     * @fires Mobizen(Service)#connect․screen․error
     * @fires Mobizen(Service)#connect․auth․error
     * @param {object} payload
     * @param {object} data
     * @todo 메시지 이름과 이벤트 이름을 통일
     */
    receive: function(payload, data) {
      var closed = false
        , type = payload.typeText
        , message = payload.msgText;

      //console.debug('doterize command', doterize(type + '-' + message));

      switch(type) {
        // 200 Channel
        case 'Channel': switch(message) {
          // 5 Response channel connection successed
          case 'ConnectConfirm':
            /**
             * @event Mobizen.Socket.Channel.Data#listen․channel․data
             * @type {Mobizen.Event}
             * @param {object} data
             * @param {string} message
             */
            this.task('listen.' + data.channelId, 'data', data, message);
          break;

          // 7 Response channel connection failed
          case 'ConnectFail':
            if (data.channelId === 1) {
              this.specific.unsupported = true;
              this.socket.screen.started = false;
              /**
               * @event Mobizen(Service)#connect․screen․error
               * @type {Mobizen.Event}
               * @param {object} data
               */
              this.socket.m.emit('connect.screen.error', data);
            }
          break;

          // 8 Request and response connection close
          case 'ConnectClose':
            if (data && data.closeType !== undefined) {
              switch(data.closeType) {
                // CHANNEL_CLOSE_MSG_ACCOUNT_RESET
                case 0:
                  this.socket.message('connect.auth.error', 'connect.auth.resetClose');
                  break;
                // CHANNEL_CLOSE_MSG_LOGOUT
                case 1:
                  this.socket.message('connect.auth.error', 'connect.auth.logoutClose');
                  break;
              }
            }

            this.protocol.close();
          break;

          default: this.error(payload, data);
        }
        break;

        // 201 Noop
        case 'Noop': break;

        // 204 Draw
        case 'Draw': break;

        // 208 Process
        case 'Process': switch(message) {
          // 1 Response process list
          case 'Item':
          // 3 Response process image
          case 'Image':
          // 5 Receive process kill
          case 'Kill':
            this.task('notify', 'data', type + message, data);
          break;

          default: this.error(payload, data);
        }
        break;

        // 209 File
        case 'File': switch(message) {
          // 1 Response file list
          case 'PathList':
            /**
             * @event Mobizen.Socket.Channel.Data#file․external․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            closed = this.task('file.external', 'data', data);
            /**
             * @event Mobizen.Socket.Channel.Data#files․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            !closed && this.task('files', 'data', data);
            break;

           // 2 Receive file list end
          case 'PathListEnd':
            /**
             * @event Mobizen.Socket.Channel.Data#file․external․end
             * @type {Mobizen.Event}
             */
            closed = this.task('file.external', 'destroy');
            /**
             * @event Mobizen.Socket.Channel.Data#files․end
             * @type {Mobizen.Event}
             */
            !closed && this.task('files', 'destroy');
            break;

          // 4 Response delete file
          case 'Delete':
            /**
             * @event Mobizen.Socket.Channel.Data#file․delete․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('file.delete', 'data', data);
            break;

          // 6 Response change file name
          case 'Rename':
            /**
             * @event Mobizen.Socket.Channel.Data#file․rename․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('file.rename', 'data', data);
            break;

          // 8 Response create folder result
          case 'MakeFolder':
            /**
             * @event Mobizen.Socket.Channel.Data#file․create․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('file.create', 'data', data);
            break;

          // 13 Receive find file data
          case 'FindList':
            data.$channel = 'data';
            /**
             * @event Mobizen.Socket.Channel.Data#file․find․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('file.find', 'data', data);
            break;

          // 14 Receive find file end
          case 'FindListEnd':
            /**
             * @event Mobizen.Socket.Channel.Data#file․find․end
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('file.find', 'destroy', data);
            break;

          // 102 Receive file copy/move result
          case 'CopyMove':
            //this.task('file.copymove', 'data', data, message);
            this.tasks['file.copymove'].id = data.id;
            break;

          // 103 Receive file transfer start
          case 'TransferStart':
          // 104 Receive file transfer position
          case 'TransferPosition':
          // 105 Receive file transfer complete
          case 'TransferComplete':
          // 106 Receive file transfer end
          case 'TransferEnd':
            /**
             * @event Mobizen.Socket.Channel.Data#file․copymove․data
             * @type {Mobizen.Event}
             * @param {object} data
             * @param {string} message
             */
            this.task('file.copymove', 'data', data, message.replace('Transfer', ''));
            break;

          // 108 Receive file transfer cancel
          case 'Cancel':
            /**
             * @event Mobizen.Socket.Channel.Data#file․copymove․cancel
             * @type {Mobizen.Event}
             * @param {object} data
             * @param {string} message
             */
            this.task('file.copymove', 'cancel', data, message);
            break;

          // 109 Receive error of not enough space
          case 'NotEnoughSpace':
          // 110 Receive error of not exist file
          case 'NotExistFile':
          // 111 Receive unknown error
          case 'Error':
            /**
             * @event Mobizen.Socket.Channel.Data#file․copymove․error
             * @type {Mobizen.Event}
             * @param {object} data
             * @param {string} message
             */
            this.task('file.copymove', 'error', data, message);
            break;

          default: this.error(payload, data);
        }
        break;

        // 220 Remote
        case 'Remote': switch(message) {
          // 0 Request(receive) viewer info
          case 'ViewerInfoRequest':
            // connect.js로 이관됨 그러나 요청과 응답형식으로 구현되지 않음
            break;

          // 51 Response host info
          case 'HostInfo':
            // connect.js로 이관됨
            break;

          // 72 Response login info
          case 'HttpLoginId':
            //console.debug('HttpLoginId', data);
            /**
             * @event Mobizen.Socket.Channel.Data#login․browser․end
             * @type {Mobizen.Event}
             * @param {object} data
             */
            /**
             * @event Mobizen.Socket.Channel.Data#login․local․end
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('login.' + (data.type == 1 && 'browser' || 'local'), 'destroy', data);
            break;

          // 102 Receive network type error
          case 'NetworkTypeError':
            this.protocol.close();
            break;
          default: this.error(payload, data);
        }
        break;

        // 232 Record
        case 'Record': switch(message) {
          // 1 Response screen record toggle result
          case 'Toggle':
            /**
             * @event Mobizen.Socket.Channel.Data#record․end
             * @type {Mobizen.Event}
             * @param {object} data
             */
            closed = this.task('record', 'destroy', data);
            !closed && this.task('notify', 'data', type + message, data);
            break;

          default: this.error(payload, data);
        }
        break;

        // 234 Input
        case 'Input': switch(message) {
          // 0 Response intput status
          case 'Status':
            /**
             * @event Mobizen.Socket.Channel.Data#input․status․data
             * @type {Mobizen.Event}
             * @param {object} data
             * @param {string} type
             */
            this.task('input.status', 'data', data, 'state');
            break;

          // 2 Response input text paste result
          case 'Paste':
            /**
             * @event Mobizen.Socket.Channel.Data#input․paste․end
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('input.paste', 'destroy', data);
            break;

          // 5 Receive cursor focus state
          case 'Focus':
            this.task('input.status', 'data', data, 'focus');
            break;

          default: this.error(payload, data);
        }
        break;

        // 235 Notify
        case 'Notify': switch(message) {
          // 10 Receive on delete a file of media
          case 'DeleteMedia':
            this.task('notify', 'data', message, {
              $channel: 'data',
              items: data.items,
              kind: data.type
            });
            break;

          // 4 Receive on power on/off
          case 'Power':
            /**
             * @event Mobizen.Socket.Channel.Data#notify․screen․end
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('notify.screen', 'destroy', data);
            this.task('notify', 'data', message, data);
            break;

          // 8-1 Receive on a new photo item added
          case 'Photo':
          // 8-2 Receive on new video item added
          case 'Video':
          // 8-3 Receive on a new music item added
          case 'Music':
            data.$channel = 'data';
          // 0 Receive on detect a new SMS
          /* falls through */
          case 'SMS':
          // 1 Receive on ring of phone call
          case 'PhoneCall':
          // 2 Receive on detect a new email
          case 'Mail':
          // 3 Receive on detect a new MMS
          case 'MMS':
          // 5 Receive on battery status change
          //case 'Battery':
          // 6 Receive on detect a new running application
          case 'App':

          // 9 Receive on detect a new call log added
          case 'NewCallLog':
          // 11 Receive on detect a call log removed
          case 'DeleteCallLog':
          // 12 Receive on detect a new contact added
          case 'NewContact':
          // 13 Receive on detect a contact removed
          case 'DeleteContact':
          // 14 Receive on detect a contact updated
          case 'UpdateContact':

          // 15 Receive on detect a new text message removed
          case 'MessageDetect':
          // 16 Receive on detect sent of message
          case 'MessageSent':
          // 17 Receive on detect a text message removed
          case 'MessageDelete':
          // 18 Receive on detect a message contact removed
          case 'MessageContactDelete':
          // 19 Receive on detect device tracking changed
          case 'UpdateTrackingConfig':
            /**
             * @event Mobizen.Socket.Channel.Data#notify․data
             * @type {Mobizen.Event}
             * @param {string} message
             * @param {object} data
             */
            this.task('notify', 'data', message, data);
            break;

          default: this.error(payload, data);
        }
        break;

        // 236 Device
        case 'Device': switch(message) {
          // 5 Receive settings accessiblity of device
          case 'SettingsAccessiblity':
            break;

          // 1 Receive device info
          case 'Info':
          // 4 Receive storage size of device
          case 'DiskSize':
          // 13 Receive SMS backup state
          case 'SMSbackup':
            this.specific[message] = data;

            // Check Lastest Message Receive
            if ( undefined !== this.specific.Info
              && undefined !== this.specific.SMSbackup
              && undefined !== this.specific.DiskSize) {
              /**
               * @event Mobizen.Socket.Channel.Data#status․end
               * @type {Mobizen.Event}
               * @param {object} data
               */
              this.task('status', 'destroy', this.specific);
            }
            break;

          // 12 Receive SD card info
          case 'SDCardInfo':
            /**
             * @event Mobizen.Socket.Channel.Data#sdcard․end
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('sdcard', 'destroy', data);
            break;

          // 14 Receive battery state of device
          case 'Battery':
            this.task('notify', 'data', message, data);
            break;

          // 15 Receive possible state of capture on device
          case 'Capture':
            if (data.enable === 0) {
              this.specific.uncaptured = true;
              this.task('notify', 'data', message);
            }
            break;

          // 18 Receive possible state of inject permession
          case 'Inject':
            if (data.enable === 0 && this.specific.apkforsec) {
              this.specific.uncontrolled = true;
              this.task('notify', 'data', message);
            }
            break;

          default: this.error(payload, data);
        }
        break;

        // 237 Archive
        case 'Archive': switch(message) {
          // 1 Response a result of backup
          case 'Backup':
            /**
             * @event Mobizen.Socket.Channel.Local#backup․start
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.socket.local.task('backup', 'start', data);
            break;

          // 3 Receive backup file count
          case 'DownloadCount':
          // 4 Receive current file transfer info
          case 'DownloadItemInfo':
          // 5 Receive current file transfer position
          case 'DownloadItemPosition':
          // 6 Receive current file transfer end
          case 'DownloadItemEnd':
          // 7 Receive file transfer end
          case 'DownloadEnd':
            /**
             * @event Mobizen.Socket.Channel.Local#restore․update
             * @type {Mobizen.Event}
             * @param {object} data
             * @param {string} type
             * @param {string} message
             */
            this.socket.local.task('restore', 'update', data, 'restore', message.replace('Download', ''));
            break;

          // 31 Response backup folders info
          case 'FolderInfo':
            /**
             * @event Mobizen.Socket.Channel.Local#backup․info
             * @type {Mobizen.Event}
             * @param {object} data
             * @param {string} type
             */
            this.socket.local.task('backup', 'info', data, 'backup');
            break;

          // 20 Receive an error of not enough space
          case 'NotEnoughSpace':
          // 100 Receive an error of unknown
          case 'Error':
            this.socket.local.task('restore', 'error', data, 'restore', message);
            break;

          // 200 Receive restore terminate
          case 'Terminate':
            /**
             * @event Mobizen.Socket.Channel.Local#restore․end
             * @type {Mobizen.Event}
             * @param {string} type
             */
            this.socket.local.task('restore', 'end', 'restore');
            break;

          default: this.error(payload, data);
        }
        break;

        // 242 Media
        case 'Media': switch(message) {
          // 1 Response total count of media
          case 'Data':
          // 2-1 Receive a photo data
          case 'Photo':
          // 2-2 Receive a video data
          case 'Video':
          // 2-3 Receive a music data
          case 'Music':
          // 3 Receive media data end
          case 'DataEnd':
          // 10 Receive an error
          case 'Error':

            var listener = {
              'Photo': 'media.photos',
              'Video': 'media.videos',
              'Music': 'media.music'
            }[message] || this.listener
            , event = {
              'Data': 'start',
              'DataEnd': 'end',
              'Error': 'error'
            }[message] || 'data';

            /**
             * @event Mobizen.Socket.Channel.Data#media․photos․error
             * @type {Mobizen.Event}
             * @param {string} channel - The name of channel of socket.
             */
            /**
             * @event Mobizen.Socket.Channel.Data#media․videos․error
             * @type {Mobizen.Event}
             * @param {string} channel - The name of channel of socket.
             */
            /**
             * @event Mobizen.Socket.Channel.Data#media․music․error
             * @type {Mobizen.Event}
             * @param {string} channel - The name of channel of socket.
             */
            if (event == 'error') {
              return this.task(listener, 'error', 'data');
            }

            /**
             * @event Mobizen.Socket.Channel.Data#media․photos․end
             * @type {Mobizen.Event}
             * @param {string} channel - The name of channel of socket.
             */
            /**
             * @event Mobizen.Socket.Channel.Data#media․videos․end
             * @type {Mobizen.Event}
             * @param {string} channel - The name of channel of socket.
             */
            /**
             * @event Mobizen.Socket.Channel.Data#media․music․end
             * @type {Mobizen.Event}
             * @param {string} channel - The name of channel of socket.
             */
            if (event == 'end') {
              return this.task(listener, 'destroy', 'data');
            }

            data.$channel = 'data';

            /**
             * @event Mobizen.Socket.Channel.Data#media․photos․start
             * @type {Mobizen.Event}
             * @param {object} data
             */
            /**
             * @event Mobizen.Socket.Channel.Data#media․videos․start
             * @type {Mobizen.Event}
             * @param {object} data
             */
            /**
             * @event Mobizen.Socket.Channel.Data#media․music․start
             * @type {Mobizen.Event}
             * @param {object} data
             */

            /**
             * @event Mobizen.Socket.Channel.Data#media․photos․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            /**
             * @event Mobizen.Socket.Channel.Data#media․videos․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            /**
             * @event Mobizen.Socket.Channel.Data#media․music․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task(listener, event, data);

            // FIXED: DataEnd event fired on wrong module
            if (data && data.kind) {
              this.listener = {
                '1': 'media.photos',
                '2': 'media.videos',
                '3': 'media.music'
              }[data.kind];
            }
            break;

          // 5 Response a data of media preview
          case 'Preview':
          // 11 Receive preview error
          case 'PreviewError':
            if (message == 'Preview') data.thumbnail = true;
            /**
             * @event Mobizen.Socket.Channel.Data#media․thumbnail․end
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('preview.' + data.kind + '-' + data.id, 'destroy', data);
            break;

          // 101 Response the single data of media
          case 'SingleData':
            data.$channel = 'data';
            /**
             * @event Mobizen.Socket.Channel.Data#media․search․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('media.search', 'data', data);
            break;

          default: this.error(payload, data);
        }
        break;

        // 243 CallLog
        case 'CallLog': switch(message) {
          // 3 Response total count of call logs
          case 'TotalCount':
            this.send('calllog.all');
            /**
             * @event Mobizen.Socket.Channel.Data#calllog․start
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('calllog', 'start', data);
            break;

          // 4 Receive not found error
          case 'NotFound':
            this.task('calllog', 'destroy', data);
            break;

          // 21 Receive a data of call log
          case 'AllData':
            /**
             * @event Mobizen.Socket.Channel.Data#calllog․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('calllog', 'data', data);
            break;

          // 22 Receive data transfer end
          case 'AllEnd':
            /**
             * @event Mobizen.Socket.Channel.Data#calllog․end
             * @type {Mobizen.Event}
             */
            this.task('calllog', 'destroy');
            break;

          // 35 Response delete call log result
          case 'Delete':
            /**
             * @event Mobizen.Socket.Channel.Data#calllog․delete․end
             * @type {Mobizen.Event}
             * @param {object} data
             * @todo calllog 앱에서 응답처리 없음
             */
            this.task('calllog.delete', 'destroy', data);
            break;

          // 100 Receive an error of unknown
          case 'Error':
            /**
             * @event Mobizen.Socket.Channel.Data#calllog․error
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('calllog', 'error', data);
            break;

          default: this.error(payload, data);
        }
        break;

        // 244 Contact
        case 'Contact': switch(message) {
          // 3 Response total count of contact
          case 'TotalCount':
            this.send('contacts.all');
            /**
             * @event Mobizen.Socket.Channel.Data#contacts․start
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contacts', 'start', data);
            break;

          // 4 Receive not found error
          case 'NotFound':
            this.task('contacts', 'destroy', data);
            /**
             * @event Mobizen.Socket.Channel.Data#contact․id․error
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact.id', 'error', data);
            /**
             * @event Mobizen.Socket.Channel.Data#contact․avatar․end
             * @type {Mobizen.Event}
             * @param {object} data
             * @todo 리스너 없음
             */
            this.task('contact.avatar', 'destroy', data);
            break;

          // 5 Receive cancel signal
          case 'Cancel':
            break;

          // 11 Response the result of delete a contact
          case 'Delete':
            /**
             * @event Mobizen.Socket.Channel.Data#contact․delete․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact.delete', 'data', data);
            break;

          // 21 Response the result of create a contact
          case 'Create':
            /**
             * @event Mobizen.Socket.Channel.Data#contact․create․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact.create', 'data', data);
            break;

          // 31 Response the result of aggregation
          case 'Aggregation':
            /**
             * @event Mobizen.Socket.Channel.Data#contact․aggregation․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact.aggregation', 'data', data);
            break;

          // 41 Response the result of add a new field
          case 'NewField':
            /**
             * @event Mobizen.Socket.Channel.Data#contact․insert․field․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact.insert.field', 'data', data);
            break;

          // 51 Response the result of remove a field
          case 'RemoveField':
            /**
             * @event Mobizen.Socket.Channel.Data#contact․delete․field․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact.delete.field', 'data', data);
            break;

          // 61 Response the result of update field
          case 'UpdateField':
            /**
             * @event Mobizen.Socket.Channel.Data#contact․update․field․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact.update.field', 'data', data);
            break;

          // 81 Receive a data of contact
          case 'AllData':
          // 2 Receive a data of contact
          case 'Contacts':
            /**
             * @event Mobizen.Socket.Channel.Data#contacts․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contacts', 'data', data);
            break;

          // 82 Receive contact data transfer end
          case 'AllEnd':
            /**
             * @event Mobizen.Socket.Channel.Data#contacts․end
             * @type {Mobizen.Event}
             */
            this.task('contacts', 'destroy');
            break;

          // 71 Response group data
          case 'Group':
            /**
             * @event Mobizen.Socket.Channel.Data#contact․groups․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact.groups', 'data', data);
            break;

          // 72 Response a contact data
          case 'Data':
            /**
             * @event Mobizen.Socket.Channel.Data#contact․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact', 'data', data);
            break;

          // 86 Response the data of single contact
          case 'SingleContact':
            /**
             * @event Mobizen.Socket.Channel.Data#contact․single․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact.single', 'data', data);
            break;

          // 91 Response the data of avatar
          case 'Avatar':
            /**
             * @event Mobizen.Socket.Channel.Data#contact․avatar․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact.avatar', 'data', data);
            break;

          // 93 Response the contact id
          case 'ContactId':
            /**
             * @event Mobizen.Socket.Channel.Data#contact․id․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contact.id', 'data', data);
            break;

          // 100 Receive error of unknown
          case 'Error':
            /**
             * @event Mobizen.Socket.Channel.Data#contacts․error
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('contacts', 'error', data);
            break;

          default: this.error(payload, data);
        }
        break;

        // 245 SMS
        case 'SMS': switch(message) {
          // 1 Response all SMS count
          case 'Contacts':
            /**
             * @event Mobizen.Socket.Channel.Data#message․contacts․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('message.contacts', 'data', data);
            break;

          // 3 Response a data of conversation
          case 'Conversation':
            /**
             * @event Mobizen.Socket.Channel.Data#message․conversation․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('message.conversation', 'data', data);
            break;

          // 5 Response the result of message send
          case 'MessageSend':
            /**
             * @event Mobizen.Socket.Channel.Data#message․send․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('message.send', 'data', data);
            break;

          // 7 Response the result of message delete
          case 'MessageDelete':
            /**
             * @event Mobizen.Socket.Channel.Data#message․delete․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('message.delete', 'data', data);
            break;

          // 9 Response the result of message search
          case 'Search':
            /**
             * @event Mobizen.Socket.Channel.Data#message․search․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('message.search', 'data', data);
            break;

          // 11 Response the result of delete contact
          case 'ContactDelete':
            /**
             * @event Mobizen.Socket.Channel.Data#message․contact․delete․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('message.contact.delete', 'data', data);
            break;

          // 100 Receive an error of unknown
          case 'Error':
            /**
             * @event Mobizen.Socket.Channel.Data#message․error
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('message', 'error', data);
            break;

          default: error(payload, data);
        }
        break;

        // 246 Share
        case 'Share': switch(message) {
          // 11 Receive the share app transfer start
          case 'AppInfoStart':
            /**
             * @event Mobizen.Socket.Channel.Data#share․apps․start
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('share.apps', 'start', data);
            break;

          // 12 Receive the share app data
          case 'AppInfoData':
            /**
             * @event Mobizen.Socket.Channel.Data#share․apps․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('share.apps', 'data', data);
            break;

          // 13 Receive the share app transfer end
          case 'AppInfoEnd':
            /**
             * @event Mobizen.Socket.Channel.Data#share․apps․end
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('share.apps', 'end', data);
            break;

          // 15 Response content share result
          case 'ContentShare':
            /**
             * @event Mobizen.Socket.Channel.Data#share․contents․end
             * @type {Mobizen.Event}
             */
            this.task('share.contents', 'destroy');
            break;

          // 100 Receive an error of unknown
          case 'Error':
            /**
             * @event Mobizen.Socket.Channel.Data#share․apps․error
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('share.apps', 'error', data);
            break;

          default: error(payload, data);
        }
        break;

        // 249 FindDevice
        case 'FindDevice': switch(message) {
          // 11 Response the result of location
          case 'Location':
            /**
             * @event Mobizen.Socket.Channel.Data#finddevice․location․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('finddevice.location', 'data', data);
            break;

          // 21 Response the result of track
          case 'Track':
            /**
             * @event Mobizen.Socket.Channel.Data#finddevice․track․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('finddevice.track', 'data', data);
            break;

          // 31 Response the result of ring
          case 'Ring':
            /**
             * @event Mobizen.Socket.Channel.Data#finddevice․ring․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('finddevice.ring', 'data', data);
            break;
          // 33 Response the result of ring
          case 'RingStatus':
            /**
             * @event Mobizen.Socket.Channel.Data#finddevice․ring․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('finddevice.ringstatus', 'data', data);
            break;
          // 34 Response the result of ring
          case 'RingChangeNoti':
            /**
             * @event Mobizen.Socket.Channel.Data#finddevice․ringchangenoti․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            //this.task('finddevice.ringchangenoti', 'data', data);
            this.task('notify', 'data', message, data);
            break;
          // 41 Response the result of lock screen
          case 'LockScreen':
            /**
             * @event Mobizen.Socket.Channel.Data#finddevice․lockscreen․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('finddevice.lockscreen', 'data', data);
            break;

          // 51 Response the result of reset device
          case 'ResetPhone':
            /**
             * @event Mobizen.Socket.Channel.Data#finddevice․resetphone․data
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('finddevice.resetphone', 'data', data);
            break;

          // 100 Receive an error of unknown
          case 'Error':
            /**
             * @event Mobizen.Socket.Channel.Data#finddevice․error
             * @type {Mobizen.Event}
             * @param {object} data
             */
            this.task('finddevice', 'error', data);
            break;

          default: error(payload, data);
        }
        break;

        default: this.error(payload, data);
      }
    },

    /**
     * @param {string} channel - The name of channel of socket.
     */
    open: function(channel) {
      console.log('Data.open', channel);

      if (channel == 'screen') {
        if (this.socket.noscreen) return;
      }

      if (this.socket.type == 'www') {
        console.info(channel + ' channel listen request');

        var channelId = {'screen': 1, 'file': 2}[channel];

        if (channelId == 1) {
          // 스크린 채널 요청은 응답이 있음
          this.request('listen.' + channelId, {
            channelId: channelId,
            guid: this.socket.params.instantId
          }).on('data'
          /**
           * @listens Mobizen.Socket.Channel.Data#listen․channel․data
           * @memberof Mobizen.Socket.Channel.Data~
           * @param {object} data
           * @param {string} message
           */
          , function ondatalistenchannel(data, message) {
            console.info('#' + data.channelId + ' channel listen response', data, message);
            this.socket.connect(channel);
          }.bind(this));

        } else {

          this.send('listen.' + channelId, {
            channelId: channelId,
            guid: this.socket.params.instantId
          });
        }

      } else {
        this.socket.connect(channel);
      }
    },

    /**
     * @method
     */
    close: function() {
      this.send('close');
    },

    /**
     * @param {string} type
     * @param {object} data
     */
    draw: function(type, data) {
      this.send('draw.' + type, data);
    },

    /**
     * @return {Mobizen.Socket.Channel~Task} event emmiter
     */
    status: function() {
      var p = Mobizen.Platform
        , viewerName = p.isChrome ? 'Chrome' : p.isFirefox ? 'Firefox' : p.isSafari ? 'Safari' : 'IE'
        , OSName = p.isMac ? 'MAC' : p.isWin ? 'Window' : p.isIOS ? 'iOS' : 'Unknown';

      this.send('device');
      this.send('disksize');

      return this.tasks.status || (this.tasks.status = this.sequence('viewer', {
        type: 'request',
        params: {
          isRegisteredViewer: 0,
          userid: this.socket.params.user.id,
          connectId: this.socket.params.connectId || 'Unknown',
          viewerName: viewerName,
          OSName: OSName,
          IP: 'Unknown',
          MAC: 'Unknown'
        }
      }));
    }
  });


  /**
   * Inner functions
   */

  /**
   * @memberof Mobizen.Socket.Channel.Data~
   * @param {string} str
   * @return {string} capitalized string
   */
  /*
  function capitalize(str) {
    return str.replace(/(^|-|\s|\.)[a-z]{1}/g, function(r){
      return r.replace(/(-|\s|\.)/, '').toUpperCase();
    });
  }
  */

  /**
   * Converts a doterized string into all lower case separated by dots.
   * @memberof Mobizen.Socket.Channel.Data~
   * @param {string} str
   * @return {string} doted string
   */
  /*
  function doterize(str) {
    return str.replace(/([a-z\d])([A-Z])/g, '$1.$2').toLowerCase();
  }
  */


  /*
   * Exporting modules
   */

  Mobizen.Channel.Data = Data;

})(this);
comments powered by Disqus