/// <summary>
        /// Creates a conference in Telmex.
        /// </summary>
        /// <param name="conference">The conference to create.</param>
        /// <returns>The just created <see cref="Telmex.Conference"/>.</returns>
        public Conference CreateConference(Conference conference)
        {
            // Get the responsible defaults from the config settings
            var section = ConfigurationManager.GetSection("telmex") as TelmexConfigurationSection;

            return CreateConference(
                conference.StartsOn,
                Convert.ToInt32(conference.Duration.TotalMinutes),
                conference.Participants,
                conference.Name,
                section.DefaultResponsibleId,
                section.DefaultResponsibleEmail);
        }
        public void SetRoomInfo(Conference conference)
        {
            // Save the hint
            HintConference = conference;

            // Set the conference description
            labelConferenceInfo.Text = String.Format("Create a room {0} that starts on {1} with a duration of {2} hours ({3} minutes).",
                !String.IsNullOrWhiteSpace(conference.Name) ? "named \"" + conference.Name + "\"" : "without name",
                conference.StartsOn.ToString("yyyy/MM/dd HH:mm"),
                conference.Duration.ToString(@"hh\:mm"),
                conference.Duration.TotalMinutes.ToString());

            // Set the default participants number by the hint
            if (comboParticipants.Items.Contains(conference.Participants))
                comboParticipants.SelectedItem = conference.Participants;
            else
                comboParticipants.SelectedItem = conference.Participants < 2 ? 2 : 10;
        }
        public ConferenceRibbon()
            : base(Globals.Factory.GetRibbonFactory())
        {
            InitializeComponent();

            // Set here the position of the ribbon because a known issue
            // of the Visual Studio 2010 Ribbon Designer
            this.groupConference.Position = this.Factory.RibbonPosition.BeforeOfficeId("GroupAppointmentMoreOptions");

            // Set-up the configuration entry-points
            this.buttonConfigure.Click += (s, e) => { ShowOptions(); };
            this.groupConference.DialogLauncherClick += (s, e) => { ShowOptions(); };

            // The conference magic
            this.buttonSetupConference.Click += (s, e) =>
                {
                    // This should take into account when the user doesn't complete
                    // all the required data; is not elegant, but for now is ok.
                    // mcastagnasso: two years later, "for now" meant "for ever".
                    if (!TelmexConfigurationSection.IsConfigured())
                        new ConfigureWindow().ShowDialog();
                    if (!TelmexConfigurationSection.IsConfigured())
                        return;

                    // For now, we only handle appointments (no emails).
                    var inspector = this.Context as Inspector;
                    var meeting = inspector.CurrentItem as AppointmentItem;

                    // Set up the conference info
                    var conf = new Conference();
                    conf.StartsOn = meeting.Start;
                    // Now set the participants number to a very high one (prev. conf.Participants = meeting.Recipients.Count;)
                    conf.Participants = 20;

                    // If there is no subject, use the organizer name
                    conf.Name = !String.IsNullOrWhiteSpace(meeting.Subject) ? meeting.Subject : meeting.Recipients[1].Name;
                    conf.Duration = new TimeSpan(0, meeting.Duration, 0);

                    // Set the tolerance, before and after the schedule
                    var tolerance = new TimeSpan(0, 30, 0);
                    conf.StartsOn = conf.StartsOn.Subtract(tolerance);
                    conf.Duration = conf.Duration.Add(tolerance + tolerance);

                    // Create the conference!
                    var api = new TelmexService();
                    api.Login();
                    var createdConference = api.CreateConference(conf);

                    var roomInfo = String.Format(
                        "Starts on: {0}.\nDuration: {1}.\nRoom number: {2}.\nPin: {3}.\nFrom USA, call {4} option 9.\nFrom Argentina, call {5}.\n\nNote that you can enter the conference 30 minutes before and after the scheduled.\n",
                        createdConference.StartsOn.Add(tolerance).ToString("yyyy/MM/dd HH:mm"),
                        createdConference.Duration.Subtract(tolerance + tolerance).ToString(@"hh\:mm"),
                        createdConference.Room,
                        createdConference.Pin,
                        createdConference.RemoteCallPhone,
                        createdConference.LocalCallPhone);

                    var document = inspector.WordEditor as Document;
                    document.Range().InsertBefore(roomInfo);
                };
        }
        /// <summary>
        /// Creates a conference in Telmex.
        /// </summary>
        /// <param name="start">The starting date (year, month, day) and starting time (hour, minutes).</param>
        /// <param name="duration">The duration of the room, in minutes. The room is allocated in spans of 30 minutes, rounded up.</param>
        /// <param name="participants">The maximum number of concurrent participants.</param>
        /// <param name="description">A friendly description, used in the admin tool.</param>
        /// <param name="responsibleId">The Telmex identifier of the responsible.</param>
        /// <param name="responsibleEmail">The email of the responsible.</param>
        /// <returns>The just created <see cref="Telmex.Conference"/>.</returns>
        public Conference CreateConference(DateTime start, int duration, int participants, string description, string responsibleId, string responsibleEmail)
        {
            if (duration < 1)
                throw new ArgumentOutOfRangeException("duration");

            if (participants < 2)
                throw new ArgumentOutOfRangeException("participants");

            if (String.IsNullOrWhiteSpace("description"))
                throw new ArgumentException("description");

            if (!this.IsLoggedIn)
                throw new InvalidOperationException("Service not logged in.");

            // Round up the duration
            duration = duration - (duration % 30) + ((duration % 30) > 0 ? 30 : 0);

            // Setup the conference request
            HttpWebRequest conferenceRequest = HttpWebRequest.Create(ApiBaseUrl + ApiCreateRoomUrl) as HttpWebRequest;
            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("descripcion_c", description);
            parameters.Add("x_dia_c", start.Day.ToString());
            parameters.Add("x_mes_c", start.Month.ToString());
            parameters.Add("x_ano_c", start.Year.ToString());
            parameters.Add("x_hora_c", start.ToString("HH:mm"));
            parameters.Add("participantes_c", participants.ToString());
            parameters.Add("duracion_c", new TimeSpan(0, duration, 0).ToString(@"hh\:mm"));
            parameters.Add("responsable_c", responsibleId);
            parameters.Add("Submit", "Crear");

            // Reuse the login cookie
            conferenceRequest.CookieContainer = cookieJar;

            // Post
            HttpWebResponse conferenceResponse = conferenceRequest.Post(parameters);

            // Read the response
            string conferenceRawData = conferenceResponse.ReadString();

            // Get the pseudo-captcha value (we cannot read it as xml because is just loosy html)
            string captchaValue = conferenceRawData.Substring(conferenceRawData.IndexOf("clave_temp") + 21, 6);

            // Setup the confirmation request
            HttpWebRequest confirmation = HttpWebRequest.Create(ApiBaseUrl + ApiCreateRoomUrl) as HttpWebRequest;
            parameters.Add("responsable_mail", responsibleEmail);
            parameters.Remove("Submit");
            parameters.Add("Submit", "Validar");
            parameters.Add("validacion", captchaValue);
            parameters.Add("clave_temp", captchaValue);

            // Reuse the login cookie
            confirmation.CookieContainer = cookieJar;

            var confirmationResponse = confirmation.Post(parameters);

            // Read the response
            string confirmationRawData = confirmationResponse.ReadString();

            // Set-up the result
            var conference = new Conference();

            // Again... loosy html. I hate myself for doing this,
            // but there is no option.
            conference.Room = confirmationRawData.Substring(confirmationRawData.IndexOf("El numero de sala correspondiente es:") + 37, 3);
            conference.Pin = confirmationRawData.Substring(confirmationRawData.IndexOf("La clave para ingresar a la conferencia es:") + 43, 5);
            conference.LocalCallPhone = confirmationRawData.Substring(confirmationRawData.IndexOf("El numero de acceso al servicio es:") + 36, 12);
            conference.RemoteCallPhone = confirmationRawData.Substring(confirmationRawData.IndexOf("(ARGENTINA) o") + 14, 14);
            conference.Duration = new TimeSpan(0, duration, 0);
            conference.Name = description;
            conference.Participants = participants;
            conference.StartsOn = start;

            return conference;
        }