/**
 * This file is part of the vscode-helpers distribution.
 * Copyright (c) Marcel Joachim Kloubert.
 *
 * vscode-helpers is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, version 3.
 *
 * vscode-helpers is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */ import * as _ from 'lodash' ; import * as Moment from 'moment' ; import * as vscode from 'vscode' ; import * as vscode_helpers from '../index' ; param { any [ ] } args return { TResult | PromiseLike < TResult > } export type InvokeAfterAction < TResult = any > = ( ... args : any [ ] ) => TResult | PromiseLike < TResult > ; /**
 * Additional options for 'waitWhile()' function.
 */ export interface WaitWhileOptions { /**
     * A timeout, in milliseconds.
     */ timeout ? : number ; /**
     * The optional time, in milliseconds, to wait until next check.
     */ timeUntilNextCheck ? : number ; } /**
 * A stopwatch.
 */ export class StopWatch { private _startTime : Moment . Moment | false = false ; /**
     * Gets if the stop watch is running or not.
     */ public get isRunning ( ) : boolean { return Moment . isMoment ( this . _startTime ) ; } return public start ( ) { this . _startTime = Moment . utc ( ) ; return this ; } return { number } public stop ( ) { const NOW = Moment . utc ( ) ; const START_TIME = this . _startTime ; this . _startTime = false ; if ( Moment . isMoment ( START_TIME ) ) { return NOW . diff ( START_TIME , 'ms' , true ) ; } } } param { Function } callback param { number } ms param { any [ ] } args return { vscode . Disposable } export function createInterval ( callback , ms , ... args ) { ms = parseInt ( vscode_helpers . toStringSafe ( ms ) . trim ( ) ) ; if ( isNaN ( ms ) ) { ms = 1000 ; } const TIMER = setInterval . apply ( null , [ < any > callback , ms ] . concat ( vscode_helpers . asArray ( args , false ) ) ) ; return { dispose : ( ) => { clearInterval ( TIMER ) ; } , } ; } param { Function } callback param { number } ms param { any [ ] } args return { vscode . Disposable } export function createTimeout ( callback , ms , ... args ) { ms = parseInt ( vscode_helpers . toStringSafe ( ms ) . trim ( ) ) ; if ( isNaN ( ms ) ) { ms = 1000 ; } const TIMER = setTimeout . apply ( null , [ < any > callback , ms ] . concat ( vscode_helpers . asArray ( args , false ) ) ) ; return { dispose : ( ) => { clearTimeout ( TIMER ) ; } , } ; } param { Function } action param { number } ms param { any [ ] } args return { Promise < TResult > } export function invokeAfter < TResult = any > ( action , ms ? , ... args ) { const ACTION_ARGS = args . filter ( ( x , index ) => { return index >= 2 ; } ) ; ms = parseInt ( vscode_helpers . toStringSafe ( ms ) . trim ( ) ) ; if ( isNaN ( ms ) ) { ms = 1000 ; } return new Promise < TResult > ( ( resolve , reject ) => { const COMPLETED = vscode_helpers . createCompletedAction ( resolve , reject ) ; try { setTimeout ( ( ) => { try { Promise . resolve ( action . apply ( null , ACTION_ARGS ) ) . then ( ( result ) => { COMPLETED ( null , result ) ; } ) . catch ( ( err ) => { COMPLETED ( err ) ; } ) ; } catch ( e ) { COMPLETED ( e ) ; } } , ms ) ; } catch ( e ) { COMPLETED ( e ) ; } } ) ; } param { number } ms export async function sleep ( ms ? ) { await invokeAfter ( ( ) => { } , ms ) ; } return { StopWatch } export function startWatch ( ) { return ( new StopWatch ( ) ) . start ( ) ; } param { NodeJS . Timer } intervalId return { boolean } export function tryClearInterval ( intervalId ) { try { if ( ! _ . isNil ( intervalId ) ) { clearInterval ( intervalId ) ; } return true ; } catch ( e ) { return false ; } } param { NodeJS . Timer } timeoutId return { boolean } export function tryClearTimeout ( timeoutId ) { try { if ( ! _ . isNil ( timeoutId ) ) { clearTimeout ( timeoutId ) ; } return true ; } catch ( e ) { return false ; } } param { Function } predicate param { WaitWhileOptions } return { Promise < boolean > } export async function waitWhile ( predicate , opts ? ) { if ( ! opts ) { opts = < any > { } ; } const TIME_UNTIL_NEXT_CHECK = parseInt ( vscode_helpers . toStringSafe ( opts . timeUntilNextCheck ) . trim ( ) ) ; const TIMEOUT = parseInt ( vscode_helpers . toStringSafe ( opts . timeout ) . trim ( ) ) ; let runUntil = false ; if ( ! isNaN ( TIMEOUT ) ) { runUntil = Moment . utc ( ) . add ( TIMEOUT , 'ms' ) ; } let wait ; do { const NOW = Moment . utc ( ) ; if ( false !== runUntil ) { if ( NOW . isAfter ( runUntil ) ) { return false ; } } wait = vscode_helpers . toBooleanSafe ( await Promise . resolve ( predicate ( ) ) ) ; if ( wait ) { if ( ! isNaN ( TIME_UNTIL_NEXT_CHECK ) ) { await sleep ( TIME_UNTIL_NEXT_CHECK ) ; } } } while ( wait ) ; return true ; }