//------------------------------------------------------------------------------
// <copyright file="SchedulerAdapterClient.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <summary>
//      The client implementation for the scheduler adapter
// </summary>
//------------------------------------------------------------------------------
namespace SampleBroker
{
    using System;
    using System.Collections.Generic;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.Text;
    using Microsoft.Hpc.Scheduler.Properties;
    using Microsoft.Hpc.Scheduler.Session.Interface;

    /// <summary>
    /// The client implementation for the scheduler adapter
    /// </summary>
    internal class SchedulerAdapterClient : DuplexClientBase<ISchedulerAdapterAsync>, ISchedulerAdapter
    {
        /// <summary>
        /// Stores the timeout
        /// </summary>
        private static readonly TimeSpan SchedulerAdapterTimeout = TimeSpan.FromMinutes(30);

        /// <summary>
        /// Initializes a new instance of the SchedulerAdapterClient class
        /// </summary>
        /// <param name="headnode">indicating the headnode</param>
        /// <param name="instanceContext">indicating the instance context</param>
        /// <param name="binding">indicating the binding</param>
        public SchedulerAdapterClient(string headnode, InstanceContext instanceContext, Binding binding)
            : base(instanceContext, binding, new EndpointAddress(String.Format("net.tcp://{0}:9092/SchedulerDelegation", headnode)))
        {
            this.InnerChannel.OperationTimeout = SchedulerAdapterTimeout;

            foreach (OperationDescription op in this.Endpoint.Contract.Operations)
            {
                DataContractSerializerOperationBehavior dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>() as DataContractSerializerOperationBehavior;
                if (dataContractBehavior != null)
                {
                    dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
                }
            }
        }

        /// <summary>
        /// Start to subscribe the job and task event
        /// </summary>
        /// <param name="jobid">indicating the job id</param>
        /// <param name="autoMax">indicating the auto max property of the job</param>
        /// <param name="autoMin">indicating the auto min property of the job</param>
        public void RegisterJob(int jobid, out int autoMax, out int autoMin)
        {
            this.Channel.RegisterJob(jobid, out autoMax, out autoMin);
        }

        /// <summary>
        /// Update the job's properties
        /// </summary>
        /// <param name="jobid">the job id</param>
        /// <param name="properties">the properties table</param>
        /// <returns>returns a value indicating whether update successfully</returns>
        public bool UpdateBrokerInfo(int jobid, Dictionary<string, object> properties)
        {
            // Does not need this operation
            throw new NotSupportedException();
        }

        /// <summary>
        /// Finish a service job with the reason
        /// </summary>
        /// <param name="jobid">the job id</param>
        /// <param name="reason">the reason string</param>
        public void FinishJob(int jobid, string reason)
        {
            this.Channel.FinishJob(jobid, reason);
        }

        /// <summary>
        /// Add a node to job's exclude node list
        /// </summary>
        /// <param name="jobid">the job id</param>
        /// <param name="nodeName">name of the node to be excluded</param>
        /// <param name="maxExcludeNodeCount">maximum number of nodes that could be excluded</param>
        /// <returns>true if the node is successfully blacklisted, or the job is failed. false otherwise</returns>
        public bool ExcludeNode(int jobid, string nodeName, int maxExcludeNodeCount)
        {
            // Does not need this operation
            throw new NotSupportedException();
        }
    }
}
