/*!
 * Copyright 2017 Vpn.Email network security technology Canada Inc. All Rights Reserved.
 *
 * Vpn.Email network technolog Canada Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as childPress from 'child_process'
import Imap from './imap'
export interface VE_IimapPool {
    execImap: execImap;
    isAlias: boolean;
	name: string;
}

export class execImap {
	private fock: childPress.ChildProcess
	private imap: Imap
	public ready = false
	
	public saveBusy = true
	public quireLength = 0
	private errorCount = 0
	private saveCallBack = null
	

	private fockConnect () {
		this.fock = childPress.fork ( 'imapSub', [ this.listenFolder, this.saveFolder ], { env: this.user })
		//console.log ( this.fock.connected, this.fock.pid )
		this.fock.on ( 'exit', err => {
			if ( err !== 1 ) {
				console.log ( 'execImap exit with 0 re-run' )
				return this.fockConnect ()
			}
			console.log ( 'execImap exit with 1 caont rerun' )
			this.EndCall ()
		})

		this.fock.on ( 'message', cmd => {

			this.saveBusy = false
			
			if ( typeof cmd === 'boolean' ) {
				
				if ( this.saveCallBack ) {
					
					this.saveCallBack ( cmd )
					return this.saveCallBack = null
				}
				
				if ( cmd ) {
					this.ready = cmd
					this.saveBusy = false
					this.errorCount = 0
					if ( this.reConnectReady && typeof this.reConnectReady === 'function')
						return this.reConnectReady ()
				}
					
				return this.ready = cmd
			}

			const kk = new Buffer ( cmd )
			this.readNewMail ( kk )
					
		})
	}

	private connect () {
		if ( this.doFock )
			return this.fockConnect ()
		this.imap = new Imap ( this.user, this.listenFolder, true, buffer => { this.readNewMail ( buffer )}, ready => {
			this.ready = ready
			this.saveBusy = false
			if ( ready ) {
				
				this.errorCount = 0
				if ( this.reConnectReady && typeof this.reConnectReady === 'function') {
					console.log ('execImap =====================> reConnect this.reConnectReady ()!')
					return this.reConnectReady ()
				}
				console.log ('execImap =====================> Connect ready!')
					
			}
				
			//console.log ( `listen[${this.listenFolder}],save[${this.saveFolder}]`, ' got imap ready: ', ready )
		}, err => {
			console.log ('')
			//			exit without try re-connect
			if ( err === 1 )
				return this.EndCall ()
			this.errorCount ++
			if ( this.errorCount < 10 )
				return this.connect ()
			process.exit (1)
		})
	}

	private imapSendMail = ( buffer: Buffer, CallBack ) => {
		
		if ( ! this.ready ) {
			return CallBack ( new Error ('not ready'))
		}
			
		if ( this.saveBusy ) {
			if ( this.imap.imap._queue.length )
				console.log ( 'imapSendMail wait', this.saveFolder, this.ready, this.saveBusy, this.imap.imap._queue.length )
			return CallBack ( new Error ('busy'))
		}
			
		this.saveBusy = true

		return this.imap.save ( buffer, this.saveFolder, err => {
			this.saveBusy = false
			return CallBack ( err )
		})
	}

	private fockSendMessage ( buffer: Buffer, CallBack ) {

		if ( ! this.ready ) {
			return CallBack ( new Error ( 'waiting' ))
		}

		this.saveBusy = true

		this.fock.send ( buffer )

		const _CallBack = ( success ) => {
			this.saveCallBack = null
			this.saveBusy = false
			return CallBack ( success ? null : new Error ('saveErr'))
		}

		return this.saveCallBack = _CallBack

	}

	
	
	public sendMessage ( buffer: Buffer, CallBack ) {
		if ( this.doFock )
			return this.fockSendMessage ( buffer, CallBack )
		return this.imapSendMail ( buffer, CallBack )
	}


	public sendMainMessage ( buffer: Buffer, CallBack ) {

		return this.sendMessage ( buffer, CallBack )
	}

	constructor ( private user: IinputData, private listenFolder: string, private saveFolder: string, private readNewMail: ( message: Buffer ) => void, private reConnectReady: () => void, 
	private doFock: boolean, private EndCall ) {
		this.saveFolder? console.log ('constructor', this.saveFolder ): null
		this.connect ()
	}

	
}