text:
Open PubNub-Messaging/PubNub-Messaging.csproj, and the example file PubnubExample.cs should demonstrate all functionality, asyncronously using delegates.
You can also view and inspect the tests for additional insight.

NuGet usage and example screencast is also available here: https://vimeo.com/pubnub/videos/search:.net/sort:date/format:detail

## Object Cleanup

For best performance after completion of all intended operations, please call the EndPendingRequests() method
of the Pubnub instance, and assign it to null. This will help ensure speedy resources cleanup when you are done
with the object.

### Important Changes in PubNub 3.7.1
1. Added wildcard channel subscribe feature.
2. Subscribe method: Renamed parameter name userCallback to subscribeCallback
3. Presence method: Renamed parameter name userCallback to presenceCallback

### Important Changes in PubNub 3.7
1. Added channelgroup feature for subscribe, presence, unsubscribe, presence unsubscribe, user state and PAM grant/audit/revoke.
2. Push notification feature supporting MPNS for windows phone 8 client.
3. Added pnsdk param to URL request
4. Store in history option for publish

### Important Changes in PubNub 3.6
1. Renamed property name HeartbeatInterval to LocalClientHeartbeatInterval.
2. New properties PresenceHeartbeat, PresenceHeartbeatInterval were added.
3. Additional optional parameters showUUIDList, includeUserState for HereNow method.
4. New methods GlobalHereNow, WhereNow, SetUserState, GetUserState, SetLocalUserState, GetLocalUserState and ChangeUUID
5. UserState data in the response format of presence events.

### Important Changes in PubNub 3.5
1. The Error Callback method signature has changed. Now, instead of a string, a PubnubClientError object will be passed to a callback of choice with error details (via the error object). To support this, all operation method signatures are modified.
2. PubNub Access Manager (PAM) to grant/revoke/audit access to channels.
3. Fixed bug where sometimes when machine would sleep/resume it would create a bad presence state.

### Generic method type support
Currently all the generic methods support string and object types only. Strong types will be supported in future.

## Sample Code
A completel running demo app which includes the sample code below is available in the PubNub Message project [by way of the
PubnubExample.cs](PubNub-Messaging/PubnubExample.cs) file.  [The tests](/PubNub-Messaging.Tests) are also a great reference.

### Instantiate a Pubnub instance

```c#
//Basic usage for subscribe and publish
Pubnub pubnub = new Pubnub(publishKey:"demo", subscribeKey:"demo");

//optionally, with secret key
Pubnub pubnub = new Pubnub(publishKey:"demo", subscribeKey:"demo", secretKey:"demo");

//optionally, with SSL and cipher key. This would enable encryption/decryption. enableSSL is boolean to toggle HTTP(S).
Pubnub pubnub = new Pubnub(publishKey:"demo", subscribeKey:"demo", secretKey:"demo", cipherKey:"", enableSSL:true);

```

### Subscribe to a channel

```c#
pubnub.Subscribe<string>(channel:"mychannel", subscribeCallback:DisplaySubscribeReturnMessage, connectCallback:DisplaySubscribeConnectStatusMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplaySubscribeReturnMessage, DisplaySubscribeConnectStatusMessage and DisplayErrorMessage are callback methods
```

### Subscribe to channel group only

```c#
pubnub.Subscribe<string>(channel="", channelGroup:"myGroup", subscribeCallback:DisplaySubscribeReturnMessage, connectCallback:DisplaySubscribeConnectStatusMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplaySubscribeReturnMessage, DisplaySubscribeConnectStatusMessage and DisplayErrorMessage are callback methods
```

### Subscribe to both channel and channel group

```c#
pubnub.Subscribe<string>(channel:"mychannel", channelGroup:"myGroup", subscribeCallback:DisplaySubscribeReturnMessage, connectCallback:DisplaySubscribeConnectStatusMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplaySubscribeReturnMessage, DisplaySubscribeConnectStatusMessage and DisplayErrorMessage are callback methods
```

### Subscribe to wildcard channel

```c#
pubnub.Subscribe<string>(channel:"foo.*", subscribeCallback:DisplaySubscribeReturnMessage, connectCallback:DisplaySubscribeConnectStatusMessage, wildcardPresenceCallback:DisplayWildCardPresenceReturnMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplaySubscribeReturnMessage, DisplaySubscribeConnectStatusMessage, DisplayWildCardPresenceReturnMessage and DisplayErrorMessage are callback methods
```

### Subscribe to wildcard channel and channel group

```c#
pubnub.Subscribe<string>(channel:"foo.*", channelGroup:"myGroup", subscribeCallback:DisplaySubscribeReturnMessage, connectCallback:DisplaySubscribeConnectStatusMessage, wildcardPresenceCallback:DisplayWildCardPresenceReturnMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplaySubscribeReturnMessage, DisplaySubscribeConnectStatusMessage, DisplayWildCardPresenceReturnMessage and DisplayErrorMessage are callback methods
```

### Subscribe to presence channel

```c#
pubnub.Presence<string>(channel:"mychannel", presenceCallback:DisplayPresenceReturnMessage, connectCallback:DisplayPresenceConnectStatusMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplayPresenceReturnMessage, DisplayPresenceConnectStatusMessage and DisplayErrorMessage are callback methods
```

### Subscribe to presence channel group only

```c#
pubnub.Presence<string>(channel="", channelGroup:"myGroup", presenceCallback:DisplayPresenceReturnMessage, connectCallback:DisplayPresenceConnectStatusMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplayPresenceReturnMessage, DisplayPresenceConnectStatusMessage and DisplayErrorMessage are callback methods
```

### Subscribe to both presence channel and presence channel group

```c#
pubnub.Presence<string>(channel:"mychannel", channelGroup:"myGroup", presenceCallback:DisplayPresenceReturnMessage, connectCallback:DisplayPresenceConnectStatusMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplayPresenceReturnMessage, DisplayPresenceConnectStatusMessage and DisplayErrorMessage are callback methods
```

### Publish a message

```c#
pubnub.Publish<string>(channel:"mychannel", message:"My favorite message", userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Get history

```c#
// Detailed History for previously published messages. Maximum records returned per request is = 100
pubnub.DetailedHistory<string>(channel:"mychannel", count:100, userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

// Detailed History from a specific time, ordered old to new messages.
pubnub.DetailedHistory<string>(channel:"mychannel", start:13557486057035336, userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage, reverse=true);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Who is Here, Now on this channel (HereNow)

```c#
pubnub.HereNow<string>(channel:"mychannel", userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

pubnub.HereNow<string>(channel:"mychannel", showUUID:true, includeUserState:true, userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Set the state of the user on this channel (SetUserState)

```c#
pubnub.SetUserState<string>(channel:"mychannel", jsonUserState:'{"key1":"value1"}', userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

pubnub.SetUserState<string>(channel:"mychannel", uuid:"myuuid", jsonUserState:'{"key1":"value1"}', userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Set the state of the user on this channel and channel group (SetUserState)

```c#
pubnub.SetUserState<string>(channel:"mychannel", channelGroup:"myGroup", jsonUserState:'{"key1":"value1"}', userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

pubnub.SetUserState<string>(channel:"mychannel", channelGroup:"myGroup", uuid:"myuuid", jsonUserState:'{"key1":"value1"}', userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Set the state of the user on this channel group only (SetUserState)

```c#
pubnub.SetUserState<string>(channel:"", channelGroup:"myGroup", jsonUserState:'{"key1":"value1"}', userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

pubnub.SetUserState<string>(channel:"", channelGroup:"myGroup", uuid:"myuuid", jsonUserState:'{"key1":"value1"}', userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Get the state of the user on this channel (GetUserState)

```c#
pubnub.GetUserState<string>(channel:"mychannel", userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

pubnub.GetUserState<string>(channel:"mychannel", uuid:"myAlternateUUID", userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Get the state of the user on this channel and channel group (GetUserState)

```c#
pubnub.GetUserState<string>(channel:"mychannel", channelGroup:"myGroup", userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

pubnub.GetUserState<string>(channel:"mychannel", channelGroup:"myGroup", uuid="myAlternateUUID", userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Get the state of the user on this channel group only (GetUserState)

```c#
pubnub.GetUserState<string>(channel:"", channelGroup:"myGroup", userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

pubnub.GetUserState<string>(channel:"", channelGroup:"myGroup", uuid:"myAlternateUUID", DisplayReturnMessage, errorCallback:DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Current channels for the given subscriber (WhereNow)

```c#
pubnub.WhereNow<string>(uuid:"myuuid", userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Current subscriber list for subkey (GlobalHereNow)

```c#
pubnub.GlobalHereNow<string>(showUUIDList:true, includeUserState:true, userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Unsubscribe from a channel

```c#
pubnub.Unsubscribe<string>(channel:"mychannel", subscribeCallback:DisplayReturnMessage, connectCallback:DisplaySubscribeConnectStatusMessage, disconnectCallback:DisplaySubscribeDisconnectStatusMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplayReturnMessage, DisplaySubscribeConnectStatusMessage, DisplaySubscribeDisconnectStatusMessage and DisplayErrorMessage are callback methods
```

### Unsubscribe from a channel and channel group

```c#
pubnub.Unsubscribe<string>(channel:"mychannel", channelGroup:"myGroup", subscribeCallback:DisplayReturnMessage, connectCallback:DisplaySubscribeConnectStatusMessage, disconnectCallback:DisplaySubscribeDisconnectStatusMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplayReturnMessage, DisplaySubscribeConnectStatusMessage, DisplaySubscribeDisconnectStatusMessage and DisplayErrorMessage are callback methods
```

### Unsubscribe from a Presence channel

```c#
pubnub.PresenceUnsubscribe<string>(channel:"mychannel", presenceCallback:DisplayReturnMessage, connectCallback:DisplayPresenceConnectStatusMessage, disconnectCallback:DisplayPresenceDisconnectStatusMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplayReturnMessage, DisplayPresenceConnectStatusMessage, DisplayPresenceDisconnectStatusMessage and DisplayErrorMessage are callback methods
```

### Unsubscribe from a Presence channel and Presence channel group

```c#
pubnub.PresenceUnsubscribe<string>(channel:"mychannel", channelGroup:"myGroup", presenceCallback:DisplayReturnMessage, connectCallback:DisplayPresenceConnectStatusMessage, disconnectCallback:DisplayPresenceDisconnectStatusMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplayReturnMessage, DisplayPresenceConnectStatusMessage, DisplayPresenceDisconnectStatusMessage and DisplayErrorMessage are callback methods
```

### PubNub system Time

```c#
pubnub.Time<string>(userCallback:DisplayReturnMessage, errorCallback:DisplayErrorMessage);
// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Filtering / Detecting state from within your error callback

```c#
static void DisplayErrorMessage(PubnubClientError pubnubError)
{
  Console.WriteLine(pubnubError.StatusCode)

  //Based on the severity of the error, we can filter out errors for handling or logging.
  switch (pubnubError.Severity)
  {
    case PubnubErrorSeverity.Critical:
      //This type of error needs to be handled.
      break;
    case PubnubErrorSeverity.Warn:
      //This type of error needs to be handled
      break;
    case PubnubErrorSeverity.Info:
      //This type of error can be ignored
      break;
    default:
      break;
  }

  Console.WriteLine(pubnubError.StatusCode); //Unique ID of the error

  Console.WriteLine(pubnubError.Message); //Message received from client or server. From client, it could be from .NET exception.

  if (pubnubError.DetailedDotNetException != null)
  {
    Console.WriteLine(pubnubError.IsDotNetException); // Boolean flag to check .NET exception
    Console.WriteLine(pubnubError.DetailedDotNetException.ToString()); // Full Details of .NET exception
  }

  Console.WriteLine(pubnubError.MessageSource); // Did this originate from Server or Client-side logic

  if (pubnubError.PubnubWebRequest != null)
  {
    //Captured Web Request details
    Console.WriteLine(pubnubError.PubnubWebRequest.RequestUri.ToString());
    Console.WriteLine(pubnubError.PubnubWebRequest.Headers.ToString());
  }

  if (pubnubError.PubnubWebResponse != null)
  {
    //Captured Web Response details
    Console.WriteLine(pubnubError.PubnubWebResponse.Headers.ToString());
  }

  Console.WriteLine(pubnubError.Description); // Useful for logging and troubleshooting and support
  Console.WriteLine(pubnubError.Channel); //Channel name(s) at the time of error
  Console.WriteLine(pubnubError.ErrorDateTimeGMT); //GMT time of error

}
```

### Checking the status of a published message via the callback

```c#
private static void DisplayReturnMessage(string publishResult)
{
  if (!string.IsNullOrEmpty(publishResult) && !string.IsNullOrEmpty(publishResult.Trim()))
  {
    object[] deserializedMessage = pubnub.JsonPluggableLibrary.DeserializeToObject(publishResult) as object[];
    if (deserializedMessage is object[] && deserializedMessage.Length == 3)
    {
      long statusCode = Int64.Parse(deserializedMessage[0].ToString());
      string statusMessage = (string)deserializedMessage[1];
      string channelName = (string)deserializedMessage[2];

      if (statusCode == 1 && statusMessage.ToLower() == "sent")
      {
        Console.WriteLine("Cool. Message Published");
      }
      else
      {
        Console.WriteLine("Oops. Some problem.");
      }
    }
  }
}
```

### Check the subscribe status via the callback

```
private static void DisplaySubscribeConnectStatusMessage(string result)
{
  if (!string.IsNullOrEmpty(result) && !string.IsNullOrEmpty(result.Trim()))
  {
    object[] deserializedResult = pubnub.JsonPluggableLibrary.DeserializeToObject(result) as object[];
    if (deserializedResult is object[])
    {
      int statusCode = Int32.Parse(deserializedResult[0].ToString());
      string statusMessage = (string)deserializedResult[1];
      string channel = (string)deserializedResult[2];
      if (statusCode == 1 && statusMessage.ToLower() == "connected")
      {
        Console.WriteLine("Now we are good to receive published messages");
      }
    }
  }
}
```

### PAM: Grant and revoke access for subscribes

```c#
// At the sub-key level (no channel is given)
// Grant
pubnub.GrantAccess<string>("", read=true, write=true, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);
// Revoke
pubnub.GrantAccess<string>("", read=false, write=false, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);

// At the channel level
// Grant
pubnub.GrantAccess<string>(channel:"mychannel", read=true, write=true, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);
// Revoke
pubnub.GrantAccess<string>(channel:"mychannel", read=false, write=false, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);

// At the user level. User is ID'ed via the auth key parameter.
// Grant
pubnub.GrantAccess<string>(channel:"mychannel", authenticationKey="authKey", read=true, write=true, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);
// Revoke
pubnub.GrantAccess<string>(channel:"mychannel", authenticationKey="authKey", read=false, write=false, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);

// At the channel group level
// Grant
pubnub.ChannelGroupGrantAccess<string>(channelGroup:"myGroup", authenticationKey="authKey", read=true, manage=true, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);
// Revoke
pubnub.ChannelGroupGrantAccess<string>(channelGroup:"myGroup", authenticationKey="authKey", read=false, manage=false, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### PAM: Grant and revoke access for Presence

```c#
// At the sub-key level (no channel is given)
// Grant
pubnub.GrantPresenceAccess<string>("", read=true, write=true, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);
// Revoke
pubnub.GrantPresenceAccess<string>("", read=false, write=false, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);

// At the channel level
// Grant
pubnub.GrantPresenceAccess<string>(channel:"mychannel", read=true, write=true, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);
// Revoke
pubnub.GrantPresenceAccess<string>(channel:"mychannel", read=false, write=false, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);

// At the user level. User is ID'ed via the auth key parameter.
// Grant
pubnub.GrantPresenceAccess<string>(channel:"mychannel", authenticationKey="authKey", read=true, write=true, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);
// Revoke
pubnub.GrantPresenceAccess<string>(channel:"mychannel", authenticationKey="authKey", read=false, write=false, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);

// At the channel group level
// Grant
pubnub.ChannelGroupGrantPresenceAccess<string>(channelGroup:"myGroup", authenticationKey="authKey", read=true, manage=true, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);
// Revoke
pubnub.ChannelGroupGrantPresenceAccess<string>(channelGroup:"myGroup", authenticationKey="authKey", read=false, manage=false, grantTimeLimitInSeconds=60, DisplayReturnMessage, DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Code snippet to audit PAM access for subscribe and presence channels/channelgroups

```
// Audit access at the sub-key level (no channel is given)
pubnub.AuditAccess<string>("",DisplayReturnMessage, DisplayErrorMessage);
pubnub.AuditPresenceAccess<string>("",DisplayReturnMessage, DisplayErrorMessage);

//Audit Access at the channel level
pubnub.AuditAccess<string>(channel:"mychannel",DisplayReturnMessage, DisplayErrorMessage);
pubnub.AuditPresenceAccess<string>(channel:"mychannel",DisplayReturnMessage, DisplayErrorMessage);

//Audit Access at the user level. User is ID'ed via the auth key parameter.
pubnub.AuditAccess<string>(channel:"mychannel", authenticationKey="authKey", DisplayReturnMessage, DisplayErrorMessage);
pubnub.AuditPresenceAccess<string>(channel:"mychannel", authenticationKey="authKey", DisplayReturnMessage, DisplayErrorMessage);

//Audit Access at channelgroup level
pubnub.ChannelGroupAuditAccess<string>(channelGroup:"myGroup", DisplayReturnMessage, DisplayErrorMessage);
pubnub.ChannelGroupAuditPresenceAccess<string>(channelGroup:"myGroup", DisplayReturnMessage, DisplayErrorMessage);

//Audit Access for channelgroup at user level.
pubnub.ChannelGroupAuditAccess<string>(channelGroup:"myGroup", authenticationKey="authKey", DisplayReturnMessage, DisplayErrorMessage);
pubnub.ChannelGroupAuditPresenceAccess<string>(channelGroup:"myGroup", authenticationKey="authKey", DisplayReturnMessage, DisplayErrorMessage);

NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods
```

### Logging

To capture the error/info messages from ErrorCallback, set config file appSettings key PubnubMessaging.PubnubErrorFilterLevel = "3" (Info). Other available values are 2 (Warning) and 1 (Critical). If config file support is not available for your client, refer errorLevel variable from Variables Reference section.
For troubleshooting purpose, low level logging option is also available. For this set config file appSettings key PubnubMessaging.LogLevel = "3" (Verbose). Other available values are 0 (Off), 1 (Error), 2 (Info) and 4 (Warning). If config file support is not available for your client, refer pubnubLogLevel variable from Variables Reference section.

## Running the Interactive Demo App

1. Open up the solution file
2. Right click on PubNub-Messaging, and set as Startup Projet
3. CTRL-F5 or F5 to run it

## Running the Tests

1. Install NUnit from http://www.nunit.org/index.php?p=download (2.6.2 is reccomended, but current/later versions should be ok)
2. Restart VS
3. Open up the solution file
4. Right click on PubNub-Messaging.Tests, and set as Startup Projet
5. Save the project
5. CTRL-F5 or F5 to run it

## Switching between .net 3.5 and 4

1. Open up the solution file
2. Right click on PubNub-x (where x is Messaging or Messaging.Tests), and set as Startup Projet
3. Right click on PubNub-x, select properties
4. Click the Application Tab
5. Set Target Framework to 3.5 or 4
6. Save the project
7. CTRL-F5 or F5 to run it

## Variables Reference

```c#
overrideTcpKeepAlive = false
```

This variable default value is set to false to consider "request.ServicePoint.SetTcpKeepAlive()" method in the code. For mono framework 2.10.9 stable release, SetTcpKeepAlive() is not supported. To support Mono, set the value of "overrideTcpKeepAlive" to true

```c#
_pubnubWebRequestCallbackIntervalInSeconds = 310
```

This variable sets the time limit in seconds for the web request to run. Applies to subscribe and presence web requests. In the example, we terminate HTTP requests after 310 seconds of not hearing back from the server.

```c#
_pubnubOperationTimeoutIntervalInSeconds = 15
```

This variable sets the time limit in seconds for the web request to run. Applies to regular operation requests like time, publish, "here now" and detailed history. In the example, we terminate HTTP requests after 15 seconds of not hearing back from the server.

```c#
_pubnubNetworkTcpCheckIntervalInSeconds = 15
```

This variable sets the time interval(heart-beat) to check internet/network/tcp connection for HTTP requests when an active request is initiated. In the example, we check network/tcp connection every 15 seconds. It is also used for re-connect interval when "overrideTcpKeepAlive" = true (for Mono framework 2.10.9). Re-connect applies only for subscribe and presence.

```c#
_pubnubNetworkCheckRetries = 50
```

This variable is to set the maximum number of re-tries for re-connect to check internet/network connection for subscribe and presence. In the example, we attempt 50 times to check connection.

```c#
_pubnubWebRequestRetryIntervalInSeconds = 10
```

This variable is to set the wait time for re-subscribe and re-presence, if the previous subscribe or presence fail. This variable is valid only when "overrideTcpKeepAlive" = false

If there is no internet/network connection after "pubnubNetworkCheckRetries" attempts for subscribe, "Unsubscribed after 50 failed retries" message will be sent and unsubscribe occurs automatically. Similary for presence, "Presence-unsubscribed after 50 failed retries"

For publish, here_now, detailed history and time, there is no attempt to re-connect. If the request fails due to http web request timeout, "Operation timeout" error be sent. If there is network/internet disconnect, error message "Network connect error" will be sent.

```c#
_pubnubPresenceHeartbeatInSeconds = 63
```

This variable is to set the heartbeat for the subscribed channel for presence before expiry. In the example, we indicate that subsciber can expire after 63 seconds if no heartbeat request is received by server.

```c#
_presenceHeartbeatIntervalInSeconds = 60
```

This variable is to set the heartbeat interval for the subscribed channel for presence before expiry. In the example, we attempt to  that subsciber can expire after 63 seconds if no heartbeat request is received by server.

```c#
_enableResumeOnReconnect = true
```

This variable default value is set to true for retry subscribe and presence to use last timetoken(before this with timetoken = 0). If the variable is set to false, retry subscribe and presence will use timetoken = 0.

```c#
pubnubEnableProxyConfig = false
```

This variable default value is set to false assuming Pubnub code don't need internet access through proxy. If proxy access is needed due to corporate policy, set the value of "pubnubEnableProxyConfig" to true and set the Pubnub property "Proxy" to the type PubnubProxy similar to the following code snippet.
          PubnubProxy proxy = new PubnubProxy();
          proxy.ProxyServer = <<Proxy Host or Server Name>>;
          proxy.ProxyPort = <<Proxy Port Number>>;
          proxy.ProxyUserName = << User Name of the proxy server account holder >>;
          proxy.ProxyPassword = << Password of the proxy server account holder >>;
          pubnub.Proxy = proxy;
At this time, Proxy feature is not supported for windows phone 7.1.

```c#
pubnubLogLevel = LoggingMethod.Level.Off
```

This variable default value is set to LoggingMethod.Level.Off. This is used to log any trace/error message that occur in the application. Other available log level options are LoggingMethod.Level.Error, LoggingMethod.Level.Info, LoggingMethod.Level.Verbose and LoggingMethod.Level.Warning. This variable is for troubleshooting purposes only.

```c#
errorLevel = PubnubErrorFilter.Level.Info
```

This variable default value is set to PubnubErrorFilter.Level.Info. This is used to filter out error messages that go to Error Callback. Other available options are Warning, Critical

```c#
IPubnubUnitTest PubnubUnitTest
```

PubnubUnitTest is a public property which is of type IPubnubUnitTest interface. This property is used to perform unit tests with stubs. The IPubnubUnitTest interface needs to be implemented and passed to PubnubUnitTest property.

```c#
IJsonPluggableLibrary JsonPluggableLibrary
```

JsonPluggableLibrary is a public property which is of type IJsonPluggableLibrary interface. This property is used to customize the JSON library usage within Pubnub API.

```c#
_enableJsonEncodingForPublish = true
```

This variable default value is set to true. It can be set to false only when already serialized string is published as message for Publish.

```c#
string AuthenticationKey
```

AuthenticationKey is a public property used to set authentication key for PAM.

```c#
string Origin
```

Origin is a public property used to set PubNub origin. Default value is set to "pubsub.pubnub.com" through _origin. The default value may change for production purposes. Please check with PubNub support on the origin value.

```c#
string SessionUUID
```

SessionUUID is a public property used to set custom UUID for subscribe/presence sessions. If there is no custom value, PubNub by default uses random GUID value.

```c#
domainName = "pubsub.pubnub.com"
```

This variable default value is set to "pubsub.pubnub.com". This variable is used only for mono runtime. This variable value will be same as "_origin"

** NOTE: ** Some variable values needs to be passed to Pubnub constructor for setup and configuration of PubNub C# API. The variables that needs to be setup are publishKey, subscribeKey, secretKey, cipherKey.

# Please direct all Support Questions and Concerns to Support@PubNub.com


text:
package com.datawizards.sparklocal.broadcast

import com.datawizards.sparklocal.SparkLocalBaseTest
import com.datawizards.sparklocal.session.{ExecutionEngine, SparkSessionAPI}
import org.apache.spark.SparkException
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner

@RunWith(classOf[JUnitRunner])
class BroadcastTest extends SparkLocalBaseTest {
  test("broadcast") {
    testBroadcast(ExecutionEngine.ScalaEager)
    testBroadcast(ExecutionEngine.ScalaLazy)
    testBroadcast(ExecutionEngine.ScalaParallel)
    testBroadcast(ExecutionEngine.ScalaParallelLazy)
    testBroadcast(ExecutionEngine.Spark)
  }

  test("broadcast with unpersist(true)") {
    testBroadcast(ExecutionEngine.ScalaEager, Some(true))
    testBroadcast(ExecutionEngine.ScalaLazy, Some(true))
    testBroadcast(ExecutionEngine.ScalaParallel, Some(true))
    testBroadcast(ExecutionEngine.ScalaParallelLazy, Some(true))
    testBroadcast(ExecutionEngine.Spark, Some(true))
  }

  test("broadcast with unpersist(false)") {
    testBroadcast(ExecutionEngine.ScalaEager, Some(false))
    testBroadcast(ExecutionEngine.ScalaLazy, Some(false))
    testBroadcast(ExecutionEngine.ScalaParallel, Some(false))
    testBroadcast(ExecutionEngine.ScalaParallelLazy, Some(false))
    testBroadcast(ExecutionEngine.Spark, Some(false))
  }

  test("broadcast.destroy - Scala - nothing happens") {
    val session = SparkSessionAPI.builder(ExecutionEngine.ScalaEager).master("local").getOrCreate()
    val b = session.broadcast(1)
    val rdd = session.createRDD(Seq(1,2,3))
    b.destroy()
    assertRDDOperationResultWithSorted(rdd.map(x => x + b.value)) {
      Array(2,3,4)
    }
  }

  test("broadcast.destroy - Spark - exception") {
    val session = SparkSessionAPI.builder(ExecutionEngine.Spark).master("local").getOrCreate()
    val b = session.broadcast(1)
    val rdd = session.createRDD(Seq(1,2,3))
    b.destroy()
    intercept[SparkException] {
      rdd.map(x => x + b.value).collect()
    }
  }

  private def testBroadcast[S <: SparkSessionAPI](executionEngine: ExecutionEngine[S], unpersist: Option[Boolean] = None): Unit = {
    val session = SparkSessionAPI.builder(executionEngine).master("local").getOrCreate()
    val b = session.broadcast(1)
    if(unpersist.isDefined)
      if(unpersist.get)
        b.unpersist(unpersist.get)
      else
        b.unpersist()
    val rdd = session.createRDD(Seq(1,2,3))
    assertRDDOperationResultWithSorted(rdd.map(x => x + b.value)) {
      Array(2,3,4)
    }
  }
}

redpajama_set_name: RedPajamaGithub


text:
[![][travis img]][travis] [![][coveralls img]][coveralls] [![][versioneye img]][versioneye]

=================

# Experimental Code

This is a staging area for projects prior to being moved to a more permanent repository.  There are no assurances of the quality of this code or if it even works.  This repository may disappear.

[travis]:https://travis-ci.org//DataSketches/experimental/builds?branch=master
[travis img]:https://secure.travis-ci.org/DataSketches/experimental.svg?branch=master

[coveralls]:https://coveralls.io/github/DataSketches/experimental?branch=master
[coveralls img]:https://coveralls.io/repos/github/DataSketches/experimental/badge.svg?branch=master

[versioneye]:https://www.versioneye.com/user/projects/5751fb047757a00034dc3c71
[versioneye img]:https://www.versioneye.com/user/projects/5751fb047757a00034dc3c71/badge.svg?style=flat


text:
/*
 * To change this template, choose Users | Templates
 * and open the template in the editor.
 */

Ext.define('sisprod.view.UserType.UpdateUserType', {
    extend: 'sisprod.view.base.BaseDataWindow',
    alias: 'widget.updateUserType',
    require: [
        'sisprod.view.base.BaseDataWindow'
    ],
    messages:{
        isUserTypeDefaultLabel: 'Is Users Default',
        userTypeNameLabel:'Name'
    },
    autoMappingOptions: {
        autoMapping: false
    },
    title: 'Update User Type',
    modal: true,
    width: 400,
    initComponent:function(){
        var me=this;
        me.formOptions= {
        bodyPadding: 2,
        items: [
            {
                xtype: 'hiddenfield',
                name: 'idUserType'
            },
            {
                xtype: 'checkboxfield',
                name: 'defaultUserType',
                fieldLabel: me.messages.isUserTypeDefaultLabel,
                inputValue:true,
                anchor: '100%',
                maxLength: 50
            },
            {
                xtype: 'textfield',
                grow: true,
                name: 'userTypeName',
                fieldLabel:me.messages.userTypeNameLabel,
                fieldStyle: {
                    textTransform: 'uppercase'
                },
                anchor: '100%',
                allowBlank: false,
                maxLength: 100
            }
        ]
        };
        me.callParent(arguments);
    }
});


text:
require 'spec_helper'

describe EY::Serverside::Adapter::Deploy do
  it_should_behave_like "it installs engineyard-serverside"

  it_should_behave_like "it accepts app"
  it_should_behave_like "it accepts account_name"
  it_should_behave_like "it accepts archive"
  it_should_behave_like "it accepts clean"
  it_should_behave_like "it accepts environment_name"
  it_should_behave_like "it accepts framework_env"
  it_should_behave_like "it accepts git"
  it_should_behave_like "it accepts instances"
  it_should_behave_like "it accepts migrate"
  it_should_behave_like "it accepts ref"
  it_should_behave_like "it accepts stack"
  it_should_behave_like "it accepts verbose"
  it_should_behave_like "it accepts serverside_version"

  it_should_require :app
  it_should_require :environment_name, %w[2.0.0 2.1.0 2.2.0 2.3.0]
  it_should_require :account_name,     %w[2.0.0 2.1.0 2.2.0 2.3.0]
  it_should_require :instances
  it_should_require :framework_env
  it_should_require :stack
  it_should_require :ref,  %w[1.6.4 2.0.0 2.1.0 2.2.0]
  it_should_require :git,  %w[1.6.4 2.0.0 2.1.0 2.2.0]
  it_should_require :serverside_version

  it_should_ignore_requirement :environment_name, '1.6.4'
  it_should_ignore_requirement :account_name,     '1.6.4'
  it_should_ignore_requirement :ref,              '2.3.0'

  it_should_exclude_from_command :environment_name, %w[1.6.4]
  it_should_exclude_from_command :account_name,     %w[1.6.4]
  it_should_exclude_from_command :repo,             %w[2.3.0]
  it_should_exclude_from_command :git,              %w[1.6.4 2.0.0 2.1.0 2.2.0]
  it_should_exclude_from_command :archive,          %w[1.6.4 2.0.0 2.1.0 2.2.0]
  it_should_exclude_from_command :clean,            %w[1.6.4 2.0.0 2.1.0 2.2.0 2.3.1]

  it_should_behave_like "it treats config as optional"
  it_should_behave_like "it treats migrate as optional"

  context "with valid arguments" do
    def deploy_command(&block)
      adapter = described_class.new do |arguments|
        arguments.app                = "rackapp"
        arguments.environment_name   = 'rackapp_production'
        arguments.account_name       = 'ey'
        arguments.framework_env      = 'production'
        arguments.config             = {'a' => 1}
        arguments.instances          = [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
        arguments.migrate            = 'rake db:migrate'
        arguments.ref                = 'master'
        arguments.git                = 'git@github.com:engineyard/engineyard-serverside.git'
        arguments.stack              = "nginx_unicorn"
        arguments.serverside_version = serverside_version
        block.call arguments if block
      end
      last_command(adapter)
    end

    def archive_deploy_command(&block)
      adapter = described_class.new do |arguments|
        arguments.archive            = 'https://github.com/engineyard/engineyard-serverside/archive/master.zip'
        arguments.app                = "rackapp"
        arguments.environment_name   = 'rackapp_production'
        arguments.account_name       = 'ey'
        arguments.framework_env      = 'production'
        arguments.config             = {'a' => 1}
        arguments.instances          = [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
        arguments.migrate            = 'rake db:migrate'
        arguments.stack              = "nginx_unicorn"
        arguments.serverside_version = serverside_version
        block.call arguments if block_given?
      end
      last_command(adapter)
    end

    it "puts the config in the command line as json" do
      deploy_command.should =~ /--config '#{Regexp.quote '{"a":1}'}'/
    end

    it "invokes exactly the right command" do
      deploy_command.should == [
        "engineyard-serverside",
        "_#{serverside_version}_",
        "deploy",
        "--account-name ey",
        "--app rackapp",
        "--config '{\"a\":1}'",
        "--environment-name rackapp_production",
        "--framework-env production",
        "--git git@github.com:engineyard/engineyard-serverside.git",
        "--instance-names localhost:chewie",
        "--instance-roles localhost:han,solo",
        "--instances localhost",
        "--migrate 'rake db:migrate'",
        "--ref master",
        "--stack nginx_unicorn",
      ].join(' ')
    end

    %w[1.6.4 2.0.0 2.1.0 2.2.0].each do |version|
      context "on version ~> #{version}" do
        it "sets --repo instead of --git flag" do
          git_repo = 'git@github.com:engineyard/engineyard-serverside.git'
          command = deploy_command do |args|
            args.serverside_version = version
            args.git = git_repo
          end

          expect(command).to match(/--repo #{Regexp.escape(git_repo)}/)
          expect(command).not_to match(/--git/)
        end

        it "raises if both --archive and --git are set (you must specify git)" do
          expect do
            command = deploy_command do |args|
              args.archive            = "url"
              args.serverside_version = version
            end
          end.to raise_error(ArgumentError)
        end
      end
    end

    context "on version ~> 2.3.0" do
      let(:version) { "2.3.0" }

      it "sets --git and not --repo flag" do
        git_repo = 'git@github.com:engineyard/engineyard-serverside.git'
        command = deploy_command do |args|
          args.serverside_version = version
          args.git = git_repo
        end
        expect(command).to match(/--git #{Regexp.escape(git_repo)}/)
        expect(command).not_to match(/--repo/)
      end

      it "raises if both --archive and --git are set" do
        expect do
          deploy_command do |args|
            args.serverside_version = version
            args.archive = "url"
          end
        end.to raise_error(ArgumentError)
      end

      it "raises if neither --archive nor --git are set" do
        expect do
          described_class.new do |arguments|
            arguments.app                = "rackapp"
            arguments.environment_name   = 'rackapp_production'
            arguments.account_name       = 'ey'
            arguments.framework_env      = 'production'
            arguments.config             = {'a' => 1}
            arguments.instances          = [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
            arguments.migrate            = 'rake db:migrate'
            arguments.ref                = 'master'
            arguments.stack              = "nginx_unicorn"
            arguments.serverside_version = version
          end
        end.to raise_error(ArgumentError)
      end

      it "sets --archive" do
        command = archive_deploy_command do |args|
          args.serverside_version = version
          args.archive = "url"
        end
        expect(command).to match(/--archive url/)
      end
    end
  end

  context "with git deploy" do
    let(:command) do
      adapter = described_class.new do |arguments|
        arguments.app                = "rackapp"
        arguments.environment_name   = 'rackapp_production'
        arguments.account_name       = 'ey'
        arguments.framework_env      = 'production'
        arguments.config             = {'a' => 1}
        arguments.instances          = [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
        arguments.migrate            = 'rake db:migrate'
        arguments.ref                = 'master'
        arguments.git                = 'git@github.com:engineyard/engineyard-serverside.git'
        arguments.stack              = "nginx_unicorn"
        arguments.serverside_version = '2.3.0'
      end
      last_command(adapter)
    end

    it "invokes exactly the right command" do
      command.should == [
        "engineyard-serverside",
        "_2.3.0_",
        "deploy",
        "--account-name ey",
        "--app rackapp",
        "--config '{\"a\":1}'",
        "--environment-name rackapp_production",
        "--framework-env production",
        "--git git@github.com:engineyard/engineyard-serverside.git",
        "--instance-names localhost:chewie",
        "--instance-roles localhost:han,solo",
        "--instances localhost",
        "--migrate 'rake db:migrate'",
        "--ref master",
        "--stack nginx_unicorn"
      ].join(' ')
    end
  end

  context "with package deploy" do
    let(:command) do
      adapter = described_class.new do |args|
        args.app              = "rackapp"
        args.environment_name = 'rackapp_production'
        args.account_name     = 'ey'
        args.framework_env    = 'production'
        args.instances        = [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
        args.migrate          = false
        args.stack            = "nginx_unicorn"
        args.archive          = 'https://github.com/engineyard/engineyard-serverside/archive/master.zip'
        args.serverside_version = '2.3.0'
      end

      last_command(adapter)
    end

    it "invokes exactly the right command" do
      command.should == [
        "engineyard-serverside",
        "_2.3.0_",
        "deploy",
        "--account-name ey",
        "--app rackapp",
        "--archive https://github.com/engineyard/engineyard-serverside/archive/master.zip",
        "--environment-name rackapp_production",
        "--framework-env production",
        "--instance-names localhost:chewie",
        "--instance-roles localhost:han,solo",
        "--instances localhost",
        "--no-migrate",
        "--stack nginx_unicorn"
      ].join(' ')
    end

  end

  context "with no migrate argument" do
    let(:command) do
      adapter = described_class.new do |arguments|
        arguments.app              = "rackapp"
        arguments.environment_name = 'rackapp_production'
        arguments.account_name     = 'ey'
        arguments.framework_env    = 'production'
        arguments.config           = {'a' => 1}
        arguments.instances        = [{:hostname => 'localhost', :roles => %w[han solo], :name => 'chewie'}]
        arguments.migrate          = false
        arguments.ref              = 'master'
        arguments.git              = 'git@github.com:engineyard/engineyard-serverside.git'
        arguments.stack            = "nginx_unicorn"
        arguments.serverside_version = '2.3.0'
      end
      last_command(adapter)
    end

    it "puts the config in the command line as json" do
      command.should =~ /--config '#{Regexp.quote '{"a":1}'}'/
    end

    it "invokes exactly the right command" do
      command.should == [
        "engineyard-serverside",
        "_2.3.0_",
        "deploy",
        "--account-name ey",
        "--app rackapp",
        "--config '{\"a\":1}'",
        "--environment-name rackapp_production",
        "--framework-env production",
        "--git git@github.com:engineyard/engineyard-serverside.git",
        "--instance-names localhost:chewie",
        "--instance-roles localhost:han,solo",
        "--instances localhost",
        "--no-migrate",
        "--ref master",
        "--stack nginx_unicorn",
      ].join(' ')
    end
  end
end


text:
@interface UIAPreparedCellTableView () {
    BOOL _hasUniqueSection;
    NSArray *_cells;
}

- (NSArray *)cellsForSection:(NSUInteger)section;

@end

@implementation UIAPreparedCellTableView

- (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style {
    self = [super initWithFrame:frame style:style];
    if (self != nil) {
        self.dataSource = self;
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self != nil) {
        self.dataSource = self;
    }
    return self;
}

- (BOOL)hasUniqueSection {
    return _hasUniqueSection;
}

- (void)setHasUniqueSection:(BOOL)hasUniqueSection {
    if (self->_hasUniqueSection == hasUniqueSection) return;

    self->_hasUniqueSection = hasUniqueSection;

    [self reloadData];
}

- (NSArray *)cells {
    return _cells;
}

- (void)setCells:(NSArray *)cells {
    if (self->_cells == cells) return;

    [cells retain];
    [self->_cells release];
    self->_cells = cells;

    [self reloadData];
}

- (NSArray *)cellsForSection:(NSUInteger)section {
    if (self->_hasUniqueSection) {
        return self.cells;
    } else {
        return self.cells[section];
    }
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    if (self->_hasUniqueSection) {
        return 1;
    } else {
        return [self.cells count];
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [[self cellsForSection:section] count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [self cellsForSection:indexPath.section][indexPath.row];
    dassert([cell isKindOfClass:[UITableViewCell class]]);
    return cell;
}

@end


text:
import { Host, HostV2 } from './../models/host';
import {
  HttpMethods,
  HttpConstants,
  LogCategories,
  ContainerConstants,
  ARMApiVersions,
  FunctionAppVersion,
  WorkerRuntimeLanguages,
} from './../models/constants';
import { UserService } from './user.service';
import { HostingEnvironment, InternalLoadBalancingMode } from './../models/arm/hosting-environment';
import { FunctionAppContext } from './../function-app-context';
import { CacheService } from 'app/shared/services/cache.service';
import { Injectable, Injector } from '@angular/core';
import { Headers, Response, ResponseType, ResponseContentType } from '@angular/http';
import { FunctionInfo } from 'app/shared/models/function-info';
import { HttpResult } from './../models/http-result';
import { ArmObj } from 'app/shared/models/arm/arm-obj';
import { FunctionsVersionInfoHelper, runtimeIsV1 } from 'app/shared/models/functions-version-info';
import { Constants } from 'app/shared/models/constants';
import { ArmUtil } from 'app/shared/Utilities/arm-utils';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/zip';
import { ApiProxy } from 'app/shared/models/api-proxy';
import * as jsonschema from 'jsonschema';
import { VfsObject } from 'app/shared/models/vfs-object';
import { FunctionTemplate } from 'app/shared/models/function-template';
import { HttpRunModel, Param } from 'app/shared/models/http-run';
import { FunctionKeys, FunctionKey } from 'app/shared/models/function-key';
import { BindingConfig, RuntimeExtension } from 'app/shared/models/binding';
import { HostStatus } from 'app/shared/models/host-status';
import { SiteConfig } from 'app/shared/models/arm/site-config';
import { FunctionAppEditMode } from 'app/shared/models/function-app-edit-mode';
import { Site } from 'app/shared/models/arm/site';
import { AuthSettings } from 'app/shared/models/auth-settings';
import { RunFunctionResult } from 'app/shared/models/run-function-result';
import { PortalResources } from 'app/shared/models/portal-resources';
import { ConditionalHttpClient } from 'app/shared/conditional-http-client';
import { TranslateService } from '@ngx-translate/core';
import { errorIds } from 'app/shared/models/error-ids';
import { LogService } from './log.service';
import { ExtensionInstallStatus } from '../models/extension-install-status';
import { SiteService } from './site.service';
import { ExtensionJobsStatus } from '../models/extension-jobs-status';
import { ExtensionInfo, ExtensionsJson } from 'app/shared/models/extension-info';
import { Version } from 'app/shared/Utilities/version';
import { ApplicationSettings } from 'app/shared/models/arm/application-settings';
import { ArmSiteDescriptor } from '../resourceDescriptors';
import { FunctionService } from './function.service';
import { AppSettingsHelper } from '../Utilities/application-settings-helper';

type Result<T> = Observable<HttpResult<T>>;
@Injectable()
export class FunctionAppService {
  private readonly runtime: ConditionalHttpClient;
  private readonly azure: ConditionalHttpClient;

  constructor(
    private _cacheService: CacheService,
    private _translateService: TranslateService,
    private _userService: UserService,
    private _injector: Injector,
    private _siteService: SiteService,
    private _logService: LogService,
    private _functionService: FunctionService,
    injector: Injector
  ) {
    this.runtime = new ConditionalHttpClient(
      injector,
      resourceId => this.getRuntimeToken(resourceId),
      'NoClientCertificate',
      'NotOverQuota',
      'NotStopped',
      'ReachableLoadballancer'
    );
    this.azure = new ConditionalHttpClient(
      injector,
      _ => this._userService.getStartupInfo().map(i => i.token),
      'NotOverQuota',
      'ReachableLoadballancer'
    );
  }

  private getRuntimeToken(resourceId: string): Observable<string> {
    return this._functionService.getHostKeys(resourceId).map(hostKeys => {
      return (hostKeys && hostKeys.result && `masterKey ${hostKeys.result.masterKey}`) || '';
    });
  }

  getClient(context: FunctionAppContext): ConditionalHttpClient {
    return context.urlTemplates.useNewUrls ? this.runtime : this.azure;
  }

  getApiProxies(context: FunctionAppContext): Result<ApiProxy[]> {
    return this.getClient(context).execute({ resourceId: context.site.id } /*input*/, token =>
      Observable /*query*/.zip(
        this.retrieveProxies(context, token),
        this._cacheService.get('assets/schemas/proxies.json', false, this.portalHeaders(token)),
        (p, s) => ({ proxies: p, schema: s })
      )
        .flatMap(response => this.validateAndGetProxies(response.proxies, response.schema))
    );
  }

  private retrieveProxies(context: FunctionAppContext, token: string): Observable<any> {
    return this._cacheService.get(context.urlTemplates.proxiesJsonUrl, false, this.headers(token)).catch(err =>
      err.status === 404
        ? Observable.throw({
            errorId: errorIds.proxyJsonNotFound,
            message: '',
            result: null,
          })
        : Observable.throw(err)
    );
  }

  private validateAndGetProxies(proxiesResponse: any, schemaResponse: any): Observable<ApiProxy[]> {
    let proxiesJson, schemaJson;

    try {
      proxiesJson = proxiesResponse.json();
    } catch (exception) {
      return Observable.throw({
        errorId: errorIds.proxyJsonNotValid,
        message: this._translateService.instant(PortalResources.proxyJsonInvalid).format(exception.message),
        result: null,
      });
    }

    try {
      schemaJson = schemaResponse.json();
    } catch (exception) {
      return Observable.throw({
        errorId: errorIds.proxySchemaNotValid,
        message: this._translateService.instant(PortalResources.schemaJsonInvalid).format(exception.message),
        result: null,
      });
    }

    if (proxiesJson) {
      const validateResult = jsonschema.validate(proxiesJson, schemaJson);
      if (!validateResult.valid) {
        return Observable.throw({
          errorId: errorIds.proxySchemaValidationFails,
          message: this._translateService.instant(PortalResources.error_schemaValidationProxies).format(validateResult.toString()),
          result: null,
        });
      }
    }

    return Observable.of(ApiProxy.fromJson(proxiesJson));
  }

  saveApiProxy(context: FunctionAppContext, jsonString: string): Result<Response> {
    const uri = context.urlTemplates.proxiesJsonUrl;
    this._cacheService.clearCachePrefix(uri);

    return this.getClient(context).execute({ resourceId: context.site.id }, t =>
      this._cacheService.put(uri, this.jsonHeaders(t, ['If-Match', '*']), jsonString)
    );
  }

  getFileContent(context: FunctionAppContext, file: VfsObject | string): Result<string> {
    const fileHref = typeof file === 'string' ? file : file.href;

    return this.getClient(context).execute({ resourceId: context.site.id }, t =>
      this._cacheService.get(fileHref, false, this.headers(t)).map(r => r.text())
    );
  }

  saveFile(context: FunctionAppContext, file: VfsObject | string, updatedContent: string): Result<VfsObject | string> {
    const fileHref = typeof file === 'string' ? file : file.href;

    return this.getClient(context).execute({ resourceId: context.site.id }, t =>
      this._cacheService
        .put(fileHref, this.jsonHeaders(t, ['Content-Type', 'plain/text'], ['If-Match', '*']), updatedContent)
        .map(() => file)
    );
  }

  deleteFile(context: FunctionAppContext, file: VfsObject | string, functionInfo?: FunctionInfo): Result<VfsObject | string> {
    const fileHref = typeof file === 'string' ? file : file.href;

    return this.getClient(context).execute({ resourceId: context.site.id }, t =>
      this._cacheService.delete(fileHref, this.jsonHeaders(t, ['Content-Type', 'plain/text'], ['If-Match', '*'])).map(() => file)
    );
  }

  getRuntimeGeneration(context: FunctionAppContext): Observable<string> {
    return this.getExtensionVersionFromAppSettings(context)
      .map(v => FunctionsVersionInfoHelper.getFunctionGeneration(v))
      .catch(e => {
        return Observable.of(FunctionAppVersion.v2);
      });
  }

  private getExtensionVersionFromAppSettings(context: FunctionAppContext) {
    return this._cacheService.postArm(`${context.site.id}/config/appsettings/list`).map(r => {
      const appSettingsArm: ArmObj<any> = r.json();
      return appSettingsArm.properties[Constants.runtimeVersionAppSettingName];
    });
  }

  getTemplates(context: FunctionAppContext): Result<FunctionTemplate[]> {
    // this is for dev scenario for loading custom templates
    try {
      if (localStorage.getItem('dev-templates')) {
        const devTemplate: FunctionTemplate[] = JSON.parse(localStorage.getItem('dev-templates'));
        this.localize(devTemplate);
        return Observable.of({
          isSuccessful: true,
          result: devTemplate,
          error: null,
        });
      }
    } catch (e) {
      console.error(e);
    }
    return this.azure.executeWithConditions([], { resourceId: context.site.id }, t =>
      this.getExtensionVersionFromAppSettings(context)
        .mergeMap(extensionVersion => {
          if (ArmUtil.isLinuxDynamic(context.site)) {
            extensionVersion = 'beta';
          }

          return this._cacheService.get(
            `${Constants.cdnHost}api/templates?runtime=${extensionVersion || 'latest'}&cacheBreak=${window.appsvc.cacheBreakQuery}`,
            false
          );
        })
        .map(r => {
          let templates = r.json() as FunctionTemplate[];

          // Linux Filter - Remove templates with extensions
          if (ArmUtil.isLinuxApp(context.site)) {
            templates = templates.filter(template => !template.metadata.extensions || template.metadata.extensions.length === 0);
          }

          this.localize(templates);
          return templates;
        })
    );
  }

  statusCodeToText(code: number) {
    const statusClass = Math.floor(code / 100) * 100;
    return HttpConstants.statusCodeMap[code] || HttpConstants.genericStatusCodeMap[statusClass] || 'Unknown Status Code';
  }

  runHttpFunction(
    context: FunctionAppContext,
    functionInfo: FunctionInfo,
    url: string,
    model: HttpRunModel,
    key?: Param
  ): Result<RunFunctionResult> {
    return this.runtime.executeWithConditions([], { resourceId: context.site.id }, token => {
      const content = model.body;

      const regExp = /\{([^}]+)\}/g;
      const matchesPathParams = url.match(regExp);
      const processedParams = [];

      const splitResults = url.split('?');
      if (splitResults.length === 2) {
        url = splitResults[0];
      }

      if (matchesPathParams) {
        matchesPathParams.forEach(m => {
          const name = m
            .split(':')[0]
            .replace('{', '')
            .replace('}', '');
          processedParams.push(name);
          const param = model.queryStringParams.find(p => {
            return p.name === name;
          });
          if (param) {
            url = url.replace(m, param.value);
          }
        });
      }

      let queryString = '';
      if (key) {
        queryString = `?${key.name}=${key.value}`;
      }
      model.queryStringParams.forEach(p => {
        const findResult = processedParams.find(pr => {
          return pr === p.name;
        });

        if (!findResult) {
          if (!queryString) {
            queryString += '?';
          } else {
            queryString += '&';
          }
          queryString += p.name + '=' + p.value;
        }
      });
      url = url + queryString;
      const inputBinding =
        functionInfo.config && functionInfo.config.bindings ? functionInfo.config.bindings.find(e => e.type === 'httpTrigger') : null;

      let contentType: string;
      if (!inputBinding || (inputBinding && inputBinding.webHookType)) {
        contentType = 'application/json';
      }

      const headers = this.headers(token);
      if (contentType) {
        headers.append('Content-Type', contentType);
      }

      model.headers.forEach(h => {
        headers.append(h.name, h.value);
      });

      if (!headers.get('Content-Type')) {
        headers.append('Content-Type', 'application/json');
      }

      let response: Observable<Response>;
      switch (model.method) {
        case HttpMethods.GET:
          // make sure to pass 'true' to force make a request.
          // there is no scenario where we want cached data for a function run.
          response = this._cacheService.get(url, true, headers);
          break;
        case HttpMethods.POST:
          response = this._cacheService.post(url, true, headers, content);
          break;
        case HttpMethods.DELETE:
          response = this._cacheService.delete(url, headers);
          break;
        case HttpMethods.HEAD:
          response = this._cacheService.head(url, true, headers);
          break;
        case HttpMethods.PATCH:
          response = this._cacheService.patch(url, headers, content);
          break;
        case HttpMethods.PUT:
          response = this._cacheService.put(url, headers, content);
          break;
        default:
          response = this._cacheService.send(url, model.method, true, headers, content);
          break;
      }

      return this.runFunctionInternal(context, response, functionInfo);
    });
  }

  runFunction(context: FunctionAppContext, functionInfo: FunctionInfo, content: string) {
    const url = context.urlTemplates.getRunFunctionUrl(functionInfo.name.toLocaleLowerCase());
    const _content: string = JSON.stringify({ input: content });
    let contentType: string;

    try {
      JSON.parse(_content);
      contentType = 'application/json';
    } catch (e) {
      contentType = 'plain/text';
    }

    return this.runtime.executeWithConditions([], { resourceId: context.site.id }, t =>
      this.runFunctionInternal(
        context,
        this._cacheService.post(url, true, this.headers(t, ['Content-Type', contentType]), _content),
        functionInfo
      )
    );
  }

  // TODO: [ahmels] change to Result<T>
  updateDisabledAppSettings(context: FunctionAppContext, infos: FunctionInfo[]): Observable<any> {
    if (infos.length > 0) {
      return this._siteService.getAppSettings(context.site.id, true).switchMap(r => {
        const appSettings = r.result;
        let needToUpdate = false;
        infos.forEach(info => {
          const appSettingName = `AzureWebJobs.${info.name}.Disabled`;
          if (info.config.disabled) {
            appSettings.properties[appSettingName] = 'true';
            needToUpdate = true;
          } else if (appSettings.properties[appSettingName]) {
            delete appSettings.properties[appSettingName];
            needToUpdate = true;
          }
        });

        return needToUpdate ? this._siteService.updateAppSettings(context.site.id, appSettings) : Observable.of(null);
      });
    } else {
      return Observable.of(null);
    }
  }

  getHostV1Json(context: FunctionAppContext): Result<Host> {
    return this.getClient(context).execute({ resourceId: context.site.id }, t =>
      this._cacheService.get(context.urlTemplates.hostJsonUrl, false, this.headers(t)).map(r => r.json())
    );
  }

  getHostV2V3Json(context: FunctionAppContext): Result<HostV2> {
    return this.getClient(context).execute({ resourceId: context.site.id }, t =>
      this._cacheService.get(context.urlTemplates.hostJsonUrl, false, this.headers(t)).map(r => r.json())
    );
  }

  getBindingConfig(context: FunctionAppContext): Result<BindingConfig> {
    try {
      if (localStorage.getItem('dev-bindings')) {
        const devBindings: BindingConfig = JSON.parse(localStorage.getItem('dev-bindings'));
        this.localize(devBindings);
        return Observable.of({
          isSuccessful: true,
          result: devBindings,
          error: null,
        });
      }
    } catch (e) {
      console.error(e);
    }

    return this.getClient(context).execute({ resourceId: context.site.id }, t =>
      this.getExtensionVersionFromAppSettings(context)
        .concatMap(extensionVersion => {
          if (!extensionVersion) {
            extensionVersion = 'latest';
          }

          return this._cacheService.get(
            `${Constants.cdnHost}api/bindingconfig?runtime=${extensionVersion}&cacheBreak=${window.appsvc.cacheBreakQuery}`,
            false
          );
        })
        .map(r => {
          const bindingConfig = r.json() as BindingConfig;

          // Linux Filter - remove bindings with extensions
          if (ArmUtil.isLinuxApp(context.site)) {
            const filteredBindings = bindingConfig.bindings.filter(binding => !binding.extension);
            bindingConfig.bindings = filteredBindings;
          }

          this.localize(bindingConfig);
          return bindingConfig;
        })
    );
  }

  getFunctionErrors(context: FunctionAppContext, fi: FunctionInfo, handleUnauthorized?: boolean): Result<string[]> {
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService
        .get(context.urlTemplates.getFunctionRuntimeErrorsUrl(fi.name), false, this.headers(t))
        .map(r => (r.json().errors || []) as string[])
    );
  }

  getHostErrors(context: FunctionAppContext): Result<string[]> {
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService.get(context.urlTemplates.runtimeStatusUrl, true, this.headers(t)).map(r => (r.json().errors || []) as string[])
    );
  }

  getFunctionHostStatus(context: FunctionAppContext): Result<HostStatus> {
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService.get(context.urlTemplates.runtimeStatusUrl, true, this.headers(t)).map(r => r.json() as HostStatus)
    );
  }

  getWorkerRuntimeRequired(context: FunctionAppContext): Observable<boolean> {
    return this.getFunctionHostStatus(context).map(r => {
      if (r.isSuccessful) {
        const runtimeVersion = new Version(r.result.version);
        if (this._workerRuntimeRequired(runtimeVersion)) {
          return true;
        }
      }
      return false;
    });
  }

  private _workerRuntimeRequired(runtimeVersion: Version): boolean {
    if (runtimeVersion.majorVersion && runtimeVersion.minorVersion) {
      return runtimeVersion.majorVersion === 2 && runtimeVersion.minorVersion >= 12050;
    }
    return false;
  }

  getLogs(context: FunctionAppContext, functionName: string, range?: number, force: boolean = false): Result<string> {
    const url = context.urlTemplates.getFunctionLogUrl(functionName);

    return this.getClient(context).execute({ resourceId: context.site.id }, t =>
      this._cacheService.get(url, force, this.headers(t)).concatMap(r => {
        let files: VfsObject[] = r.json();
        if (files.length > 0) {
          files = files
            .map(e => Object.assign({}, e, { parsedTime: new Date(e.mtime) }))
            .sort((a, b) => a.parsedTime.getTime() - b.parsedTime.getTime());

          const headers = range ? this.headers(t, ['Range', `bytes=-${range}`]) : this.headers(t);

          return this._cacheService.get(files.pop().href, force, headers).map(f => {
            const content = f.text();
            if (range) {
              const index = content.indexOf('\n');
              return <string>(index !== -1 ? content.substring(index + 1) : content);
            } else {
              return content;
            }
          });
        } else {
          return Observable.of('');
        }
      })
    );
  }

  getVfsObjects(context: FunctionAppContext, fi: FunctionInfo | string): Result<VfsObject[]> {
    const href = typeof fi === 'string' ? fi : fi.script_root_path_href;
    return this.getClient(context).execute({ resourceId: context.site.id }, t =>
      this._cacheService.get(href, true, this.headers(t)).map(e => <VfsObject[]>e.json())
    );
  }

  // Use createFunctionKey from function.service.ts instead unless keyValue needs to be auto-generated
  createKeyDeprecated(context: FunctionAppContext, keyName: string, keyValue: string, functionInfo?: FunctionInfo): Result<FunctionKey> {
    this.clearKeysCache(context, functionInfo);

    const url = functionInfo
      ? context.urlTemplates.getFunctionKeyUrl(functionInfo.name, keyName)
      : context.urlTemplates.getAdminKeyUrl(keyName);

    const body = keyValue
      ? JSON.stringify({
          name: keyName,
          value: keyValue,
        })
      : null;

    return this.runtime.execute({ resourceId: context.site.id }, t => {
      const req = body ? this._cacheService.put(url, this.jsonHeaders(t), body) : this._cacheService.post(url, true, this.jsonHeaders(t));
      return req.map(r => r.json() as FunctionKey);
    });
  }

  renewKey(context: FunctionAppContext, key: FunctionKey, functionInfo?: FunctionInfo): Result<FunctionKey> {
    this.clearKeysCache(context, functionInfo);

    const url = functionInfo
      ? context.urlTemplates.getFunctionKeyUrl(functionInfo.name, key.name)
      : context.urlTemplates.getAdminKeyUrl(key.name);

    return this.runtime.execute({ resourceId: context.site.id }, t => this._cacheService.post(url, true, this.jsonHeaders(t)));
  }

  private clearKeysCache(context: FunctionAppContext, functionInfo?: FunctionInfo) {
    if (functionInfo) {
      this._cacheService.clearCachePrefix(context.urlTemplates.getFunctionKeysUrl(functionInfo.name));
    } else {
      this._cacheService.clearCachePrefix(context.urlTemplates.adminKeysUrl);
      this._cacheService.clearCachePrefix(context.urlTemplates.systemKeysUrl);
    }
  }

  fireSyncTrigger(context: FunctionAppContext): void {
    if (ArmUtil.isLinuxDynamic(context.site)) {
      this._cacheService
        .postArm(`${context.site.id}/hostruntime/admin/host/synctriggers`, true)
        .subscribe(
          success => this._logService.verbose(LogCategories.syncTriggers, success),
          error => this._logService.error(LogCategories.syncTriggers, '/sync-triggers-error', error)
        );
    } else {
      const url = context.urlTemplates.syncTriggersUrl;
      this.azure
        .execute({ resourceId: context.site.id }, t => this._cacheService.post(url, true, this.jsonHeaders(t)))
        .subscribe(
          success => this._logService.verbose(LogCategories.syncTriggers, success),
          error => this._logService.error(LogCategories.syncTriggers, '/sync-triggers-error', error)
        );
    }
  }

  isSourceControlEnabled(context: FunctionAppContext): Result<boolean> {
    return this.azure.executeWithConditions(
      [],
      { resourceId: context.site.id },
      this._cacheService.getArm(`${context.site.id}/config/web`, null, ARMApiVersions.antaresApiVersion20181101).map(r => {
        const config: ArmObj<SiteConfig> = r.json();
        return !config.properties['scmType'] || config.properties['scmType'] !== 'None';
      })
    );
  }

  isSlotsSupported(appSettingsArm: ArmObj<ApplicationSettings>): boolean {
    const appSettings = !!appSettingsArm && appSettingsArm.properties;
    const [runtimeVersionAppSetting, secretStorageSetting] = [
      AppSettingsHelper.getAppSettingInfo(Constants.runtimeVersionAppSettingName, appSettings),
      AppSettingsHelper.getAppSettingInfo(Constants.secretStorageSettingsName, appSettings),
    ];
    const [runtimeVersionAppSettingValue, secretStorageSettingValue] = [
      runtimeVersionAppSetting && runtimeVersionAppSetting.value,
      secretStorageSetting && secretStorageSetting.value && secretStorageSetting.value.toLowerCase(),
    ];
    const runtimeGeneration = FunctionsVersionInfoHelper.getFunctionGeneration(runtimeVersionAppSettingValue);

    // Slots are not supported if the SecretStorageType is 'Files', so we need to determine whether this is
    // the case based on the app settings 'FUNCTIONS_EXTENSION_VERSION' and 'AzureWebJobsSecretStorageType'
    let isUsingFilesSecretStorage = true;

    if (runtimeGeneration === 'V1') {
      // For V1 Function apps, the supported values for 'AzureWebJobsSecretStorageType' are 'Files' and 'Blob'.
      // The default value is 'Files', which is used if 'AzureWebJobsSecretStorageType' is not set or is set to a non-supported value.

      if (secretStorageSettingValue === Constants.secretStorageSettingsValueBlob.toLowerCase()) {
        // AzureWebJobsSecretStorageType is explicitly set to 'Blob'
        isUsingFilesSecretStorage = false;
      } else {
        // AzureWebJobsSecretStorageType is either explicitly set to 'Files' or we are defaulting to
        // 'Files' because the setting is not configured or is configured with a non-supported value
        isUsingFilesSecretStorage = true;
      }
    } else {
      // For V2 Function apps, the supported values for 'AzureWebJobsSecretStorageType' are 'Files', 'Blob' and 'KeyVault'.
      // The default value is 'Blob', which is used if 'AzureWebJobsSecretStorageType' is not set or is set to a non-supported value.

      if (secretStorageSettingValue === Constants.secretStorageSettingsValueFiles.toLowerCase()) {
        // AzureWebJobsSecretStorageType is explicitly set to 'Files'
        isUsingFilesSecretStorage = true;
      } else {
        // AzureWebJobsSecretStorageType is either explicitly set to a supported value other than 'Files' or we are
        // defaulting to 'Blob' because the setting is not configured or is configured with a non-supported value
        isUsingFilesSecretStorage = false;
      }
    }

    return !isUsingFilesSecretStorage;
  }

  isSlot(context: FunctionAppContext | string): boolean {
    return !!this.getSlotName(context);
  }

  getSlotName(context: FunctionAppContext | string): string {
    const id = typeof context === 'string' ? context : context.site.id;
    const descriptor = new ArmSiteDescriptor(id);
    return descriptor.slot;
  }

  getSlotsList(context: FunctionAppContext | string): Result<ArmObj<Site>[]> {
    const id = typeof context === 'string' ? context : context.site.id;
    return this.isSlot(context)
      ? Observable.of({
          isSuccessful: true,
          result: [],
          error: null,
        })
      : this.azure.executeWithConditions(
          [],
          typeof context !== 'string' ? { resourceId: context.site.id } : null,
          this._cacheService.getArm(`${id}/slots`).map(r => r.json().value as ArmObj<Site>[])
        );
  }

  // TODO: [ahmels] change to Result<T>
  reachableInternalLoadBalancerApp(context: FunctionAppContext): Observable<boolean> {
    if (
      context &&
      context.site &&
      context.site.properties.hostingEnvironmentProfile &&
      context.site.properties.hostingEnvironmentProfile.id
    ) {
      return this._cacheService
        .getArm(context.site.properties.hostingEnvironmentProfile.id, false, ARMApiVersions.antaresApiVersion20181101)
        .mergeMap(r => {
          const ase: ArmObj<HostingEnvironment> = r.json();
          if (ase.properties.internalLoadBalancingMode && ase.properties.internalLoadBalancingMode !== InternalLoadBalancingMode.None) {
            return this.pingScmSite(context).map(result => result.isSuccessful);
          } else {
            return Observable.of(true);
          }
        })
        .catch(() => {
          // When ASE fetch fails don't block access to functions list
          return Observable.of(true);
        });
    } else {
      return Observable.of(true);
    }
  }

  getFunctionAppEditMode(context: FunctionAppContext): Result<FunctionAppEditMode> {
    // The we have 2 settings to check here. There is the SourceControl setting which comes from /config/web
    // and there is FUNCTION_APP_EDIT_MODE which comes from app settings.
    // editMode (true -> readWrite, false -> readOnly)
    // Table
    // |Slots | SourceControl | AppSettingValue | EditMode                      |
    // |------|---------------|-----------------|-------------------------------|
    // | No   | true          | readWrite       | ReadWriteSourceControlled     |
    // | No   | true          | readOnly        | ReadOnlySourceControlled      |
    // | No   | true          | undefined       | ReadOnlySourceControlled      |
    // | No   | false         | readWrite       | ReadWrite                     |
    // | No   | false         | readOnly        | ReadOnly                      |
    // | No   | false         | undefined       | ReadWrite                     |

    // | Yes  | true          | readWrite       | ReadWriteSourceControlled     |
    // | Yes  | true          | readOnly        | ReadOnlySourceControlled      |
    // | Yes  | true          | undefined       | ReadOnlySourceControlled      |
    // | Yes  | false         | readWrite       | ReadWrite                     |
    // | Yes  | false         | readOnly        | ReadOnly                      |
    // | Yes  | false         | undefined       | ReadOnlySlots                 |
    // |______|_______________|_________________|_______________________________|

    return this.azure.executeWithConditions(
      [],
      { resourceId: context.site.id },
      Observable.zip(
        this.isSourceControlEnabled(context),
        this._siteService.getAppSettings(context.site.id),
        this.isSlot(context)
          ? Observable.of({ isSuccessful: true, result: true, error: null })
          : this.getSlotsList(context).map(r => (r.isSuccessful ? Object.assign(r, { result: r.result.length > 0 }) : r)),
        this._functionService.getFunctions(context.site.id),
        (a, b, s, f) => ({
          sourceControlEnabled: a,
          appSettingsResponse: b,
          hasSlots: s,
          functionsInfo: f.isSuccessful ? f.result.value : [],
        })
      )
        .map(result => {
          const appSettings: ArmObj<{ [key: string]: string }> = result.appSettingsResponse.isSuccessful
            ? result.appSettingsResponse.result
            : null;

          const sourceControlled = result.sourceControlEnabled.isSuccessful && result.sourceControlEnabled.result;

          let editModeSettingString: string = appSettings ? appSettings.properties[Constants.functionAppEditModeSettingName] || '' : '';
          editModeSettingString = editModeSettingString.toLocaleLowerCase();
          const vsCreatedFunc = !!result.functionsInfo.find((fc: ArmObj<FunctionInfo>) => !!fc.properties.config.generatedBy);
          const usingRunFromZip = appSettings ? this._getRFZSetting(appSettings) !== '0' : false;
          const usingLocalCache =
            appSettings && appSettings.properties[Constants.localCacheOptionSettingName] === Constants.localCacheOptionSettingValue;
          const hasSlots = result.hasSlots.result;
          const isLinuxElastic = ArmUtil.isLinuxElastic(context.site);
          const isLinuxDynamic = ArmUtil.isLinuxDynamic(context.site);
          const isContainerApp = appSettings && appSettings.properties[ContainerConstants.appServiceStorageSetting] === 'false';
          const workerRuntime = appSettings && appSettings.properties[Constants.functionsWorkerRuntimeAppSettingsName];
          const isPython = workerRuntime && WorkerRuntimeLanguages[workerRuntime] === WorkerRuntimeLanguages.python;
          const isJava = workerRuntime && WorkerRuntimeLanguages[workerRuntime] === WorkerRuntimeLanguages.java;

          const resolveReadOnlyMode = () => {
            if (sourceControlled) {
              return FunctionAppEditMode.ReadOnlySourceControlled;
            } else if (vsCreatedFunc) {
              return FunctionAppEditMode.ReadOnlyVSGenerated;
            } else if (hasSlots) {
              return FunctionAppEditMode.ReadOnly;
            } else {
              return FunctionAppEditMode.ReadOnly;
            }
          };

          const resolveReadWriteMode = () => {
            if (sourceControlled) {
              return FunctionAppEditMode.ReadWriteSourceControlled;
            } else if (vsCreatedFunc) {
              return FunctionAppEditMode.ReadWriteVSGenerated;
            } else if (hasSlots) {
              return FunctionAppEditMode.ReadWrite;
            } else {
              return FunctionAppEditMode.ReadWrite;
            }
          };

          const resolveUndefined = () => {
            if (sourceControlled) {
              return FunctionAppEditMode.ReadOnlySourceControlled;
            } else if (vsCreatedFunc) {
              return FunctionAppEditMode.ReadOnlyVSGenerated;
            } else if (hasSlots) {
              return FunctionAppEditMode.ReadOnlySlots;
            } else {
              return FunctionAppEditMode.ReadWrite;
            }
          };

          if (usingRunFromZip) {
            return FunctionAppEditMode.ReadOnlyRunFromZip;
          } else if (usingLocalCache) {
            return FunctionAppEditMode.ReadOnlyLocalCache;
          } else if (isPython) {
            return FunctionAppEditMode.ReadOnlyPython;
          } else if (isJava) {
            return FunctionAppEditMode.ReadOnlyJava;
          } else if (isLinuxDynamic) {
            return FunctionAppEditMode.ReadOnlyLinuxDynamic;
          } else if (isContainerApp) {
            return FunctionAppEditMode.ReadOnlyBYOC;
          } else if (isLinuxElastic) {
            return FunctionAppEditMode.ReadOnlyLinuxCodeElastic;
          } else if (editModeSettingString === Constants.ReadWriteMode) {
            return resolveReadWriteMode();
          } else if (editModeSettingString === Constants.ReadOnlyMode) {
            return resolveReadOnlyMode();
          } else {
            return resolveUndefined();
          }
        })
        .catch(() => Observable.of(FunctionAppEditMode.ReadWrite))
    );
  }

  private _getRFZSetting(appSettings: ArmObj<ApplicationSettings>) {
    return (
      appSettings.properties[Constants.WebsiteUseZip] ||
      appSettings.properties[Constants.WebsiteRunFromZip] ||
      appSettings.properties[Constants.WebsiteRunFromPackage] ||
      '0'
    );
  }

  public getAuthSettings(context: FunctionAppContext): Result<AuthSettings> {
    return this.azure.executeWithConditions(
      [],
      { resourceId: context.site.id },
      this._cacheService.postArm(`${context.site.id}/config/authsettings/list`).map(r => {
        const auth: ArmObj<any> = r.json();
        return {
          easyAuthEnabled: auth.properties['enabled'] && auth.properties['unauthenticatedClientAction'] !== 1,
          AADConfigured: auth.properties['clientId'] || false,
          AADNotConfigured: auth.properties['clientId'] ? false : true,
          clientCertEnabled: context.site.properties.clientCertEnabled,
        };
      })
    );
  }

  /**
   * This method just pings the root of the SCM site. It doesn't care about the response in anyway or use it.
   */
  pingScmSite(context: FunctionAppContext): Result<boolean> {
    if (ArmUtil.isLinuxDynamic(context.site)) {
      return Observable.of({
        isSuccessful: true,
        result: true,
        error: null,
      });
    }

    return this.azure.execute({ resourceId: context.site.id }, t =>
      this._cacheService
        .get(context.urlTemplates.pingScmSiteUrl, true, this.headers(t))
        .map(_ => true)
        .catch(() => Observable.of(false))
    );
  }

  private runFunctionInternal(context: FunctionAppContext, response: Observable<Response>, functionInfo: FunctionInfo) {
    return response
      .catch((e: Response) => {
        return this.getAuthSettings(context)
          .map(r => (r.isSuccessful ? r.result : { easyAuthEnabled: false, clientCertEnabled: false }))
          .mergeMap(authSettings => {
            if (authSettings.easyAuthEnabled) {
              return Observable.of({
                status: 401,
                statusText: this.statusCodeToText(401),
                text: () => this._translateService.instant(PortalResources.functionService_authIsEnabled),
              });
            } else if (authSettings.clientCertEnabled) {
              return Observable.of({
                status: 401,
                statusText: this.statusCodeToText(401),
                text: () => this._translateService.instant(PortalResources.functionService_clientCertEnabled),
              });
            } else if (e.status === 200 && e.type === ResponseType.Error) {
              return Observable.of({
                status: 502,
                statusText: this.statusCodeToText(502),
                text: () =>
                  this._translateService.instant(PortalResources.functionService_errorRunningFunc, {
                    name: functionInfo.name,
                  }),
              });
            } else if (e.status === 0 && e.type === ResponseType.Error) {
              return Observable.of({
                status: 0,
                statusText: this.statusCodeToText(0),
                text: () => '',
              });
            } else {
              let text = '';
              try {
                text = JSON.stringify(e.json(), undefined, 2);
              } catch (ex) {
                text = e.text();
              }

              return Observable.of({
                status: e.status,
                statusText: this.statusCodeToText(e.status),
                text: () => text,
              });
            }
          });
      })
      .map(r => <RunFunctionResult>{ statusCode: r.status, statusText: this.statusCodeToText(r.status), content: r.text() });
  }

  getGeneratedSwaggerData(context: FunctionAppContext, key: string): Result<any> {
    const url: string = context.urlTemplates.getGeneratedSwaggerDataUrl;
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService.get(`${url}?code=${key}`, false, this.headers(t)).map(r => r.json())
    );
  }

  getSwaggerDocument(context: FunctionAppContext, key: string): Result<any> {
    const url: string = context.urlTemplates.getSwaggerDocumentUrl;
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService.get(`${url}?code=${key}`, false, this.headers(t)).map(r => r.json())
    );
  }

  addOrUpdateSwaggerDocument(context: FunctionAppContext, swaggerUrl: string, content: string): Result<any> {
    return this.runtime.execute(
      { resourceId: context.site.id },
      this._cacheService.post(swaggerUrl, false, this.jsonHeaders(null), content).map(r => r.json())
    );
  }

  deleteSwaggerDocument(context: FunctionAppContext, swaggerUrl: string) {
    return this.runtime.execute({ resourceId: context.site.id }, this._cacheService.delete(swaggerUrl));
  }

  saveHostJson(context: FunctionAppContext, jsonString: string): Result<any> {
    return this.getClient(context).execute({ resourceId: context.site.id }, t =>
      this._cacheService.put(context.urlTemplates.hostJsonUrl, this.jsonHeaders(t, ['If-Match', '*']), jsonString).map(r => r.json())
    );
  }

  createSystemKey(context: FunctionAppContext, keyName: string) {
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService
        .post(context.urlTemplates.getSystemKeyUrl(keyName), true, this.jsonHeaders(t, ['If-Match', '*']))
        .map(r => r.json())
    );
  }

  // Try and the list of runtime extensions install.
  // If there was an error getting the list, show an error. return an empty list.
  getHostExtensions(context: FunctionAppContext): Result<any> {
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService.get(context.urlTemplates.runtimeHostExtensionsUrl, true, this.headers(t)).map(r => r.json() as FunctionKeys)
    );
  }

  installExtension(context: FunctionAppContext, extension: RuntimeExtension): Result<ExtensionInstallStatus> {
    const requestBody = { ...extension, PostInstallActions: 'BringAppOnline' };
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService
        .post(context.urlTemplates.runtimeHostExtensionsUrl, true, this.jsonHeaders(t), requestBody)
        .map(r => r.json() as ExtensionInstallStatus)
    );
  }

  uninstallExtension(context: FunctionAppContext, extensionId: string): Result<ExtensionInstallStatus> {
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService
        .delete(context.urlTemplates.getRuntimeHostExtensionsIdUrl(extensionId), this.headers(t))
        .map(r => r.json() as ExtensionInstallStatus)
    );
  }

  getExtensionInstallStatus(context: FunctionAppContext, jobId: string): Result<ExtensionInstallStatus> {
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService
        .get(context.urlTemplates.getRuntimeHostExtensionsJobStatusUrl(jobId), true, this.headers(t))
        .map(r => r.json() as ExtensionInstallStatus)
    );
  }

  getExtensionJobsStatus(context: FunctionAppContext): Result<ExtensionJobsStatus> {
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService
        .get(context.urlTemplates.runtimeHostExtensionsJobsUrl, true, this.headers(t))
        .map(r => r.json() as ExtensionJobsStatus)
    );
  }

  getExtensionJson(context: FunctionAppContext): Result<ExtensionInfo[]> {
    return this.azure.execute({ resourceId: context.site.id }, t =>
      this._cacheService
        .get(context.urlTemplates.extensionJsonUrl, true, this.headers(t))
        .map(r => r.json() as ExtensionsJson)
        .map(r => r.extensions)
    );
  }

  updateHostState(context: FunctionAppContext, stateValue: 'offline' | 'running'): Result<any> {
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService.put(context.urlTemplates.updateHostStateUrl, this.jsonHeaders(t), `'${stateValue}'`)
    );
  }

  getSystemKey(context: FunctionAppContext): Result<FunctionKeys> {
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService.get(context.urlTemplates.systemKeysUrl, false, this.headers(t)).map(r => r.json() as FunctionKeys)
    );
  }

  getEventGridUri(context: FunctionAppContext, functionName: string): Result<string> {
    return Observable.zip(this.getSystemKey(context), this.getRuntimeGeneration(context)).map(tuple => {
      if (tuple[0].isSuccessful) {
        const generation = tuple[1];
        const eventGridName = runtimeIsV1(generation) ? Constants.eventGridName_v1 : Constants.eventGridName_v2;
        const key = tuple[0].result.keys.find(k => k.name === eventGridName);
        return {
          isSuccessful: true,
          result: key ? FunctionsVersionInfoHelper.getEventGridUri(generation, context.mainSiteUrl, functionName, key.value) : '',
          error: null,
        };
      } else {
        return (tuple[0] as any) as HttpResult<string>;
      }
    });
  }

  // // Modeled off of EventHub trigger's 'custom' tab when creating a new Event Hub connection
  // createApplicationSetting(context: FunctionAppContext, appSettingName: string, appSettingValue: string, replaceIfExists: boolean = true): Observable<any> | null {
  //     if (appSettingName && appSettingValue) {
  //         return this._cacheService.postArm(`${context.site.id}/config/appsettings/list`, true).flatMap(
  //             r => {
  //                 const appSettings: ArmObj<any> = r.json();
  //                 if (!replaceIfExists && appSettings.properties[appSettingName]) {
  //                     return Observable.of(r);
  //                 }
  //                 appSettings.properties[appSettingName] = appSettingValue;
  //                 return this._cacheService.putArm(appSettings.id, this._armService.antaresApiVersion20181101, appSettings);
  //             });
  //     } else {
  //         return null;
  //     }
  // }

  // TODO: [ahmels] change to Result<T>
  createAuthSettings(context: FunctionAppContext, newAuthSettings: Map<string, any>): Observable<any> {
    if (newAuthSettings.size > 0) {
      return this._cacheService.postArm(`${context.site.id}/config/authsettings/list`, true).flatMap(r => {
        const authSettings: ArmObj<any> = r.json();
        newAuthSettings.forEach((value, key) => {
          authSettings.properties[key] = value;
        });
        return this._cacheService.putArm(authSettings.id, null, authSettings);
      });
    } else {
      return Observable.of(null);
    }
  }

  restartFunctionsHost(context: FunctionAppContext): Result<void> {
    return this.runtime.execute({ resourceId: context.site.id }, t =>
      this._cacheService.post(context.urlTemplates.restartHostUrl, true, this.headers(t))
    );
  }

  getAppContext(resourceId: string, force?: boolean): Observable<FunctionAppContext> {
    return this._cacheService
      .getArm(resourceId, force)
      .map(r => ArmUtil.mapArmSiteToContext(r.json(), this._injector))
      .switchMap(context => {
        return Observable.zip(Observable.of(context), this.getRuntimeGeneration(context));
      })
      .switchMap(tuple => {
        const newContext = tuple[0];
        const version = tuple[1];
        newContext.urlTemplates.runtimeVersion = version;
        return Observable.of(newContext);
      });
  }

  getAppContentAsZip(context: FunctionAppContext, includeCsProj: boolean, includeAppSettings: boolean): Result<any> {
    const url = ArmUtil.isLinuxApp(context.site)
      ? `${context.mainSiteUrl}/admin/functions/download?includeCsproj=${includeCsProj}&includeAppSettings=${includeAppSettings}`
      : `${context.scmUrl}/api/functions/admin/download?includeCsproj=${includeCsProj}&includeAppSettings=${includeAppSettings}`;
    const client = ArmUtil.isLinuxApp(context.site) ? this.runtime : this.azure;

    return client.execute({ resourceId: context.site.id }, t =>
      this._cacheService
        .get(url, true, this.headers(t), null, ResponseContentType.Blob)
        .map(r => new Blob([r.blob()], { type: 'application/octet-stream' }))
    );
  }

  getFunctionTestData(context: FunctionAppContext, testDataHref: string): Observable<any> {
    return this.getClient(context).execute({ resourceId: context.site.id }, t => {
      return this._cacheService.get(testDataHref, true, this.headers(t)).map(r => r.text());
    });
  }

  // these 2 functions are only for try app service scenarios.
  // It's a hack to not have to change a lot of code since soon try will fork this anyway.
  // DO NOT use this for anything new.
  _tryFunctionsBasicAuthToken: string;
  setTryFunctionsToken(token: string) {
    this._tryFunctionsBasicAuthToken = token;
  }

  private localize(objectToLocalize: any): any {
    if (typeof objectToLocalize === 'string' && objectToLocalize.startsWith('$')) {
      const key = objectToLocalize.substring(1, objectToLocalize.length);
      objectToLocalize = this._translateService.instant(key);
    } else if (Array.isArray(objectToLocalize)) {
      for (let i = 0; i < objectToLocalize.length; i++) {
        objectToLocalize[i] = this.localize(objectToLocalize[i]);
      }
    } else if (typeof objectToLocalize === 'object') {
      for (const property in objectToLocalize) {
        if (property === 'files' || property === 'defaultValue' || property === 'function') {
          continue;
        }
        if (objectToLocalize.hasOwnProperty(property)) {
          objectToLocalize[property] = this.localize(objectToLocalize[property]);
        }
      }
    }
    return objectToLocalize;
  }

  private portalHeaders(authToken: string, ...aditionalHeaders: [string, string][]): Headers {
    const headers = aditionalHeaders.slice();
    headers.unshift(['portal-token', authToken]);
    return this.jsonHeaders.apply(this, headers);
  }

  private jsonHeaders(authTokenOrHeader: string | [string, string], ...additionalHeaders: [string, string][]): Headers {
    const headers: Array<[string, string] | string> = additionalHeaders.slice();
    headers.unshift(['Content-Type', 'application/json']);
    if (authTokenOrHeader) {
      headers.unshift(authTokenOrHeader);
    }
    return this.headers.apply(this, headers);
  }

  private headers(authTokenOrHeader: string | [string, string], ...additionalHeaders: [string, string][]): Headers {
    const headers = new Headers();
    if (typeof authTokenOrHeader === 'string' && authTokenOrHeader.length > 0) {
      if (authTokenOrHeader.startsWith('masterKey ')) {
        headers.set('Cache-Control', 'no-cache');
        headers.set('x-functions-key', authTokenOrHeader.substring('masterKey '.length));
      } else {
        headers.set('Authorization', `Bearer ${authTokenOrHeader}`);
      }
    } else if (this._tryFunctionsBasicAuthToken) {
      headers.set('Authorization', `Basic ${this._tryFunctionsBasicAuthToken}`);
    }

    if (Array.isArray(authTokenOrHeader)) {
      headers.set(authTokenOrHeader[0], authTokenOrHeader[1]);
    }

    additionalHeaders.forEach(header => {
      headers.set(header[0], header[1]);
    });

    return headers;
  }
}

/**
 * returns the file name from a VfsObject or an href
 * @param file either a VfsObject or a string representing the file's href.
 */
// function getFileName(file: VfsObject | string): string {
//     if (typeof file === 'string') {
//         // if `file` is a string, that means it's in the format:
//         //     https://<scmUrl>/api/vfs/path/to/file.ext
//         return file
//             .split('/') // [ 'https:', '', '<scmUrl>', 'api', 'vfs', 'path', 'to', 'file.ext' ]
//             .pop(); // 'file.ext'
//     } else {
//         return file.name;
//     }
// }


text:
'use strict'

const { ArrayPrototypePop, Promise } = require('../ours/primordials')

const { isIterable, isNodeStream } = require('../internal/streams/utils')

const { pipelineImpl: pl } = require('../internal/streams/pipeline')

const { finished } = require('../internal/streams/end-of-stream')

function pipeline(...streams) {
  return new Promise((resolve, reject) => {
    let signal
    let end
    const lastArg = streams[streams.length - 1]

    if (lastArg && typeof lastArg === 'object' && !isNodeStream(lastArg) && !isIterable(lastArg)) {
      const options = ArrayPrototypePop(streams)
      signal = options.signal
      end = options.end
    }

    pl(
      streams,
      (err, value) => {
        if (err) {
          reject(err)
        } else {
          resolve(value)
        }
      },
      {
        signal,
        end
      }
    )
  })
}

module.exports = {
  finished,
  pipeline
}


text:
import { psImport, psExport } from './builtins';
import { empty } from './utils';

export default class ExecutionContext {
	static DEFAULT_GLOBALS = {
		// we may not need these because they make more sense as module methods
		'import': psImport,
		'export': psExport
	}

	constructor(globals = DEFAULT_GLOBALS) {
		// we want an empty object, no prototype
		globals = empty(globals);
	}
}


text:
package com.dozenx.game.engine.Role.bean;

import org.lwjgl.util.vector.Vector3f;

/**
 * Created by colamachine on 19-8-20.
 */
public class Bounds {
  Vector3f extend;//半径
  Vector3f size;
  Vector3f center;
  Vector3f min;
  Vector3f max;

}