<commit_before>import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';

@Injectable()
export class $WebSocket {

    private static Helpers = class {
        static isPresent(obj: any): boolean {
            return obj !== undefined && obj !== null;
        }

        static isString(obj: any): boolean {
            return typeof obj === 'string';
        }

        static isArray(obj: any): boolean {
            return Array.isArray(obj);
        }

        static isFunction(obj: any): boolean {
            return typeof obj === 'function';
        }
    };

    private reconnectAttempts = 0;
    private sendQueue = [];
    private onOpenCallbacks = [];
    private onMessageCallbacks = [];
    private onErrorCallbacks = [];
    private onCloseCallbacks = [];
    private readyStateConstants = {
        'CONNECTING': 0,
        'OPEN': 1,
        'CLOSING': 2,
        'CLOSED': 3,
        'RECONNECT_ABORTED': 4
    };
    private normalCloseCode = 1000;
    private reconnectableStatusCodes = [4000];
    private socket: WebSocket;
    private dataStream: Subject<any>;
    private internalConnectionState: number;

    constructor(private url: string, private protocols?: Array<string>, private config?: WebSocketConfig, private binaryType?: BinaryType) {
        let match = new RegExp('wss?:\/\/').test(url);
        if (!match) {
            throw new Error('Invalid url provided');
        }
        this.config = config || {initialTimeout: 500, maxTimeout: 300000, reconnectIfNotNormalClose: false};
        this.binaryType = binaryType || "blob";
        this.dataStream = new Subject();
        this.connect(true);
    }

    connect(force = false) {
        // console.log("WebSocket connecting...");
        let self = this;
        if (force || !this.socket || this.socket.readyState !== this.readyStateConstants.OPEN) {
            self.socket = this.protocols ? new WebSocket(this.url, this.protocols) : new WebSocket(this.url);
            self.socket.binaryType = self.binaryType.toString();

            self.socket.onopen = (ev: Event) => {
                // console.log('onOpen: ', ev);
                this.onOpenHandler(ev);
            };
            self.socket.onmessage = (ev: MessageEvent) => {
                // console.log('onNext: ', ev.data);
                self.onMessageHandler(ev);
                this.dataStream.next(ev);
            };
            this.socket.onclose = (ev: CloseEvent) => {
                // console.log('onClose ', ev);
                self.onCloseHandler(ev);
            };

            this.socket.onerror = (ev: ErrorEvent) => {
                // console.log('onError ', ev);
                self.onErrorHandler(ev);
                this.dataStream.error(ev);
            };

        }
    }

    /**
     * Run in Block Mode
     * Return true when can send and false in socket closed
     * @param data
     * @returns {boolean}
     */
    send4Direct(data): boolean {
        let self = this;
        if (this.getReadyState() !== this.readyStateConstants.OPEN
            && this.getReadyState() !== this.readyStateConstants.CONNECTING) {
            this.connect();
        }
        self.sendQueue.push({message: data});
        if (self.socket.readyState !== self.readyStateConstants.RECONNECT_ABORTED) {
            return false;
        } else {
            self.fireQueue();
            return true;
        }
    }

    /**
     * Return Promise
     * When can Send will resolve Promise
     * When Socket closed will reject Promise
     * @param data
     * @returns {Promise<any>}
     */
    send4Promise(data): Promise<any> {
        return new Promise(
            (resolve, reject) => {
                if (this.send4Direct(data)) {
                    return resolve();
                } else {
                    return reject(Error('Socket connection has been closed'));
                }
            }
        )<commit_msg>Resolve issue #61 (#65)<commit_after>import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';

@Injectable()
export class $WebSocket {

    private static Helpers = class {
        static isPresent(obj: any): boolean {
            return obj !== undefined && obj !== null;
        }

        static isString(obj: any): boolean {
            return typeof obj === 'string';
        }

        static isArray(obj: any): boolean {
            return Array.isArray(obj);
        }

        static isFunction(obj: any): boolean {
            return typeof obj === 'function';
        }
    };

    private reconnectAttempts = 0;
    private sendQueue = [];
    private onOpenCallbacks = [];
    private onMessageCallbacks = [];
    private onErrorCallbacks = [];
    private onCloseCallbacks = [];
    private readyStateConstants = {
        'CONNECTING': 0,
        'OPEN': 1,
        'CLOSING': 2,
        'CLOSED': 3,
        'RECONNECT_ABORTED': 4
    };
    private normalCloseCode = 1000;
    private reconnectableStatusCodes = [4000];
    private socket: WebSocket;
    private dataStream: Subject<any>;
    private internalConnectionState: number;

    constructor(private url: string, private protocols?: Array<string>, private config?: WebSocketConfig, private binaryType?: BinaryType) {
        let match = new RegExp('wss?:\/\/').test(url);
        if (!match) {
            throw new Error('Invalid url provided');
        }
        this.config = config || {initialTimeout: 500, maxTimeout: 300000, reconnectIfNotNormalClose: false};
        this.binaryType = binaryType || "blob";
        this.dataStream = new Subject();
        this.connect(true);
    }

    connect(force = false) {
        // console.log("WebSocket connecting...");
        let self = this;
        if (force || !this.socket || this.socket.readyState !== this.readyStateConstants.OPEN) {
            self.socket = this.protocols ? new WebSocket(this.url, this.protocols) : new WebSocket(this.url);
            self.socket.binaryType = self.binaryType.toString();

            self.socket.onopen = (ev: Event) => {
                // console.log('onOpen: ', ev);
                this.onOpenHandler(ev);
            };
            self.socket.onmessage = (ev: MessageEvent) => {
                // console.log('onNext: ', ev.data);
                self.onMessageHandler(ev);
                this.dataStream.next(ev);
            };
            this.socket.onclose = (ev: CloseEvent) => {
                // console.log('onClose ', ev);
                self.onCloseHandler(ev);
            };

            this.socket.onerror = (ev: ErrorEvent) => {
                // console.log('onError ', ev);
                self.onErrorHandler(ev);
                this.dataStream.error(ev);
            };

        }
    }

    /**
     * Run in Block Mode
     * Return true when can send and false in socket closed
     * @param data
     * @returns {boolean}
     */
    send4Direct(data): boolean {
        let self = this;
        if (this.getReadyState() !== this.readyStateConstants.OPEN
            && this.getReadyState() !== this.readyStateConstants.CONNECTING) {
            this.connect();
        }
        self.sendQueue.push({message: data});
        if (self.socket.readyState === self.readyStateConstants.RECONNECT_ABORTED) {
            return false;
        } else {
            self.fireQueue();
            return true;
        }
    }

    /**
     * Return Promise
     * When can Send will resolve Promise
     * When Socket closed will reject Promise
     * @param data
     * @returns {Promise<any>}
     */
    send4Promise(data): Promise<any> {
        return new Promise(
            (resolve, reject) => {
                if (this.send4Direct(data)) {
                    return resolve();
                } else {
                    return reject(Error('Socket connection has been closed'));
                }
            }
        )
{'fraction_non_alphanumeric': 0.1249061326658323, 'fraction_numerical': 0.007008760951188986, 'mean_word_length': 1.8744604316546762, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2101310', 'n_tokens_mistral': 2210, 'n_tokens_neox': 2123, 'n_words': 507}