/**
 * Copyright (c) 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule RelayNetworkDebug
 * @typechecks
 * @flow
 */

'use strict';

import type {ChangeSubscription} from 'RelayInternalTypes';
import type RelayMutationRequest from 'RelayMutationRequest';
const Relay = require('RelayPublic');
import type RelayQueryRequest from 'RelayQueryRequest';

const performanceNow = require('performanceNow');

export type RelayNetworkDebuggable = {
  name: string;
  type: string;
  promise: Promise;
  logResult: (error: ?Object, response: ?Object) => void;
};

class RelayNetworkDebugger {
  _initTime: number;
  _queryID: number;
  _subscription: ChangeSubscription;

  constructor() {
    this._initTime = performanceNow();
    this._queryID = 0;
    this._subscription = Relay.Store.addNetworkSubscriber(
      request =>
        this.logRequest(createDebuggableFromRequest('Relay Query', request)),
      request =>
        this.logRequest(createDebuggableFromRequest('Relay Mutation', request))
    );
  }

  uninstall(): void {
    this._subscription.remove();
  }

  logRequest({name, type, promise, logResult}: RelayNetworkDebuggable): void {
    const id = this._queryID++;
    const timerName = `[${id}] Request Duration`;

    console.timeStamp(`START: [${id}] ${type}: ${name} →`);
    console.time(timerName);

    const onSettled = (error, response) => {
      const time = (performanceNow() - this._initTime) / 1000;
      console.timeStamp(`← END: [${id}] ${type}: ${name}`);
      console.groupCollapsed(
        `%c[${id}] ${type}: ${name} @ ${time}s`,
        `color:${error ? 'red' : 'black'};`
      );
      console.timeEnd(timerName);
      logResult(error, response);
      console.groupEnd();
    };

    promise.then(
      response => onSettled(null, response),
      error => onSettled(error, null),
    );
  }
}

function createDebuggableFromRequest(
  type: string,
  request: RelayQueryRequest | RelayMutationRequest
): RelayNetworkDebuggable {
  return {
    name: request.getDebugName(),
    type,
    promise: request.getPromise(),
    logResult(error, response) {
      console.debug(
        '%c%s\n',
        'font-size:10px; color:#333; font-family:mplus-2m-regular,menlo,' +
        'monospaced;',
        request.getQueryString()
      );
      console.log('Request variables\n', request.getVariables());
      error && console.error(error);
      response && console.log(response);
    },
  };
}

let networkDebugger: ?RelayNetworkDebugger;

const RelayNetworkDebug = {
  init(): void {
    networkDebugger && networkDebugger.uninstall();
    networkDebugger = new RelayNetworkDebugger();
  },

  logRequest(request: RelayNetworkDebuggable): void {
    networkDebugger && networkDebugger.logRequest(request);
  },
};

module.exports = RelayNetworkDebug;

@@ -1475,24 +1475,45 @@
 ation%60;%0A%0A   
+ console.timeStamp &&
  console.tim
@@ -1556,24 +1556,40 @@
 me%7D %E2%86%92%60);%0A   
+ console.time &&
  console.tim
@@ -1712,24 +1712,45 @@
  1000;%0A     
+ console.timeStamp &&
  console.tim
@@ -1806,35 +1806,21 @@
 cons
-ole.
+t 
 group
-Collapsed(%0A       
+Name =
  %60%25c
@@ -1855,16 +1855,100 @@
 %7Btime%7Ds%60
+;%0A      console.groupCollapsed ?%0A        console.groupCollapsed(%0A          groupName
 ,%0A      
@@ -1949,16 +1949,18 @@
         
+  
 %60color:$
@@ -1989,32 +1989,86 @@
 k'%7D;%60%0A      
-);%0A     
+  ) :%0A        console.log(groupName);%0A      console.timeEnd &&
  console.tim
@@ -2115,32 +2115,52 @@
 response);%0A     
+ console.groupEnd &&
  console.groupEn
@@ -2546,24 +2546,41 @@
 nse) %7B%0A     
+ console.debug &&
  console.deb

make more robust