public async Task addHeadEnd(string id, CancellationToken cancellationToken)
        {
            var token = await GetToken(cancellationToken);

            if (string.IsNullOrWhiteSpace(token))
            {
                throw new ArgumentException("Authentication required.");
            }

            _logger.Info("Adding new LineUp ");

            var httpOptions = new HttpRequestOptionsMod()
            {
                Url = _apiUrl + "/lineups/" + id,
                UserAgent = UserAgent,
                Token = token,
                CancellationToken = cancellationToken
            };

            using (var response = await _httpClient.SendAsync(httpOptions, "PUT"))
            {
            }
        }
        private async Task RecordStream(TimerInfo timer, CancellationToken cancellationToken)
        {
            var mediaStreamInfo = await GetChannelStream(timer.ChannelId, "none", CancellationToken.None);
            var duration = (timer.EndDate - RecordingHelper.GetStartTime(timer)).TotalSeconds + timer.PrePaddingSeconds;

            HttpRequestOptions httpRequestOptions = new HttpRequestOptionsMod()
            {
                Url = mediaStreamInfo.Path + "?duration=" + duration
            };

            var info = GetProgramInfoFromCache(timer.ChannelId, timer.ProgramId);
            var recordPath = RecordingPath;
            if (info.IsMovie)
            {
                recordPath = Path.Combine(recordPath, "Movies", StringHelper.RemoveSpecialCharacters(info.Name));
            }
            else
            {
                recordPath = Path.Combine(recordPath, "TV", StringHelper.RemoveSpecialCharacters(info.Name));
            }

            recordPath = Path.Combine(recordPath, RecordingHelper.GetRecordingName(timer, info));
            Directory.CreateDirectory(Path.GetDirectoryName(recordPath));

            var recording = _recordingProvider.GetAll().FirstOrDefault(x => string.Equals(x.Id, info.Id, StringComparison.OrdinalIgnoreCase));

            if (recording == null)
            {
                recording = new RecordingInfo()
                {
                    ChannelId = info.ChannelId,
                    Id = info.Id,
                    StartDate = info.StartDate,
                    EndDate = info.EndDate,
                    Genres = info.Genres ?? null,
                    IsKids = info.IsKids,
                    IsLive = info.IsLive,
                    IsMovie = info.IsMovie,
                    IsHD = info.IsHD,
                    IsNews = info.IsNews,
                    IsPremiere = info.IsPremiere,
                    IsSeries = info.IsSeries,
                    IsSports = info.IsSports,
                    IsRepeat = !info.IsPremiere,
                    Name = info.Name,
                    EpisodeTitle = info.EpisodeTitle ?? "",
                    ProgramId = info.Id,
                    HasImage = info.HasImage ?? false,
                    ImagePath = info.ImagePath ?? null,
                    ImageUrl = info.ImageUrl,
                    OriginalAirDate = info.OriginalAirDate,
                    Status = RecordingStatus.Scheduled,
                    Overview = info.Overview,
                    SeriesTimerId = info.Id.Substring(0, 10)
                };
                _recordingProvider.Add(recording);
            }

            recording.Path = recordPath;
            recording.Status = RecordingStatus.InProgress;
            _recordingProvider.Update(recording);

            try
            {
                httpRequestOptions.BufferContent = false;
                httpRequestOptions.CancellationToken = cancellationToken;
                _logger.Info("Writing file to path: " + recordPath);
                using (var response = await _httpClient.SendAsync(httpRequestOptions, "GET"))
                {
                    using (var output = File.Open(recordPath, FileMode.Create, FileAccess.Write, FileShare.Read))
                    {
                        await response.Content.CopyToAsync(output, 4096, cancellationToken);
                    }
                }

                recording.Status = RecordingStatus.Completed;
            }
            catch (OperationCanceledException)
            {
                recording.Status = RecordingStatus.Cancelled;
            }
            catch
            {
                recording.Status = RecordingStatus.Error;
            }

            _recordingProvider.Update(recording);
            _timerProvider.Delete(timer);
            _logger.Info("Recording was a success");
        }
        public async Task<List<Headend>> GetHeadends(string zipcode, CancellationToken cancellationToken)
        {
            var token = await GetToken(cancellationToken);

            var lineups = new List<Headend>();

            if (string.IsNullOrWhiteSpace(token))
            {
                return lineups;
            }

            _logger.Info("Headends on account ");
            var httpOptions = new HttpRequestOptionsMod()
            {
                Url = _apiUrl + "/headends?country=USA&postalcode=" + zipcode,
                UserAgent = UserAgent,
                Token = token,
                CancellationToken = cancellationToken,
            };

            try
            {
                using (Stream responce = await _httpClient.Get(httpOptions).ConfigureAwait(false))
                {
                    var root = _jsonSerializer.DeserializeFromStream<List<ScheduleDirect.Headends>>(responce);
                    _logger.Info("Lineups on account ");
                    if (root != null)
                    {
                        foreach (ScheduleDirect.Headends headend in root)
                        {
                            _logger.Info("Headend: " + headend.headend);
                            foreach (ScheduleDirect.Lineup lineup in headend.lineups)
                            {
                                _logger.Info("Headend: " + lineup.uri.Substring(18));
                                lineups.Add(new Headend()
                                {
                                    Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name,
                                    Id = lineup.uri.Substring(18)
                                });
                            }
                        }
                    }
                    else
                    {
                        _logger.Info("No lineups on account");
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Error("Error getting headends", ex);
            }

            return lineups;
        }
        public async Task<List<string>> getLineups(CancellationToken cancellationToken)
        {
            var token = await GetToken(cancellationToken);

            List<string> Lineups = new List<string>();

            if (!String.IsNullOrWhiteSpace(token))
            {
                _logger.Info("Lineups on account ");
                var httpOptions = new HttpRequestOptionsMod()
                {
                    Url = _apiUrl + "/lineups",
                    UserAgent = UserAgent,
                    Token = token,
                    CancellationToken = cancellationToken
                };
                try
                {
                    using (Stream responce = await _httpClient.Get(httpOptions).ConfigureAwait(false))
                    {
                        var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Lineups>(responce);
                        _logger.Info("Lineups on account ");
                        if (root.lineups != null)
                        {
                            foreach (ScheduleDirect.Lineup lineup in root.lineups)
                            {
                                _logger.Info("Lineups ID: " + lineup.lineup);
                                Lineups.Add(lineup.lineup);
                            }
                        }
                        else
                        {
                            _logger.Info("No lineups on account");
                            Lineups.Add("");
                        }
                        return Lineups;
                    }
                }
                catch (Exception e)
                {
                    _logger.Info("No lineups on account");
                }
            }
            Lineups.Add("");
            return Lineups;
        }
        public async Task<IEnumerable<ProgramInfo>> getTvGuideForChannel(string channelNumber, DateTime start,
            DateTime end, CancellationToken cancellationToken)
        {
            List<ProgramInfo> programsInfo = new List<ProgramInfo>();
            if (_channelPair.ContainsKey(channelNumber))
            {
                var token = await GetToken(cancellationToken);

                if (string.IsNullOrWhiteSpace(token))
                {
                    return programsInfo;
                }

                HttpRequestOptionsMod httpOptions = new HttpRequestOptionsMod()
                {
                    Url = _apiUrl + "/schedules",
                    UserAgent = UserAgent,
                    Token = token,
                    CancellationToken = cancellationToken
                };
                List<string> dates = new List<string>();
                int numberOfDay = 0;
                DateTime lastEntry = start;
                while (lastEntry != end)
                {
                    lastEntry = start.AddDays(numberOfDay);
                    dates.Add(lastEntry.ToString("yyyy-MM-dd"));
                    numberOfDay++;
                }
                string stationID = _channelPair[channelNumber].stationID;
                _logger.Info("Channel Station ID is: " + stationID);
                List<ScheduleDirect.RequestScheduleForChannel> requestList =
                    new List<ScheduleDirect.RequestScheduleForChannel>()
                    {
                        new ScheduleDirect.RequestScheduleForChannel()
                        {
                            stationID = stationID,
                            date = dates
                        }
                    };

                var requestString = _jsonSerializer.SerializeToString(requestList);
                _logger.Debug("Request string for schedules is: " + requestString);
                httpOptions.RequestContent = requestString;
                using (var response = await _httpClient.Post(httpOptions))
                {
                    StreamReader reader = new StreamReader(response.Content);
                    string responseString = reader.ReadToEnd();
                    var dailySchedules = _jsonSerializer.DeserializeFromString<List<ScheduleDirect.Day>>(responseString);
                    _logger.Debug("Found " + dailySchedules.Count() + " programs on " + channelNumber +
                                  " ScheduleDirect");
                    httpOptions = new HttpRequestOptionsMod()
                    {
                        Url = _apiUrl + "/programs",
                        UserAgent = UserAgent,
                        Token = token,
                        CancellationToken = cancellationToken
                    };
                    httpOptions.EnableHttpCompression = true;
                    List<string> programsID = new List<string>();
                    programsID = dailySchedules.SelectMany(d => d.programs.Select(s => s.programID)).Distinct().ToList();
                    var requestBody = "[\"" + string.Join("\", \"", programsID) + "\"]";
                    httpOptions.RequestContent = requestBody;

                    using (var innerResponse = await _httpClient.Post(httpOptions))
                    {
                        StreamReader innerReader = new StreamReader(innerResponse.Content);
                        responseString = innerReader.ReadToEnd();
                        var programDetails =
                            _jsonSerializer.DeserializeFromString<List<ScheduleDirect.ProgramDetails>>(
                                responseString);
                        Dictionary<string, ScheduleDirect.ProgramDetails> programDict =
                            programDetails.ToDictionary(p => p.programID, y => y);
                        var images =
                            await
                                GetImageForPrograms(
                                    programDetails.Where(p => p.hasImageArtwork).Select(p => p.programID).ToList(),
                                    cancellationToken);
                        var schedules = dailySchedules.SelectMany(d => d.programs);
                        foreach (ScheduleDirect.Program schedule in schedules)
                        {
                            _logger.Debug("Proccesing Schedule for statio ID " + stationID +
                                          " which corresponds to channel " + channelNumber + " and program id " +
                                          schedule.programID + " which says it has images? " +
                                          programDict[schedule.programID].hasImageArtwork);
                            var imageIndex =
                                images.FindIndex(i => i.programID == schedule.programID.Substring(0, 10));
                            if (imageIndex > -1)
                            {
                                programDict[schedule.programID].images = GetProgramLogo(images[imageIndex]);
                            }
                            programsInfo.Add(GetProgram(channelNumber, schedule, programDict[schedule.programID]));
                        }
                        _logger.Info("Finished with EPGData");
                    }
                }
            }
            return programsInfo;
        }
        public async Task<List<ScheduleDirect.ShowImages>> GetImageForPrograms(List<string> programIds,
            CancellationToken cancellationToken)
        {
            var imageIdString = "[";

            programIds.ForEach(i =>
            {
                if (!imageIdString.Contains(i.Substring(0, 10)))
                {
                    imageIdString += "\"" + i.Substring(0, 10) + "\",";
                }
                ;
            });
            imageIdString = imageIdString.TrimEnd(',') + "]";
            _logger.Debug("Json for show images = " + imageIdString);
            var httpOptions = new HttpRequestOptionsMod()
            {
                Url = _apiUrl + "/metadata/programs",
                UserAgent = UserAgent,
                CancellationToken = cancellationToken,
                RequestContent = imageIdString
            };
            List<ScheduleDirect.ShowImages> images;
            using (var innerResponse2 = await _httpClient.Post(httpOptions))
            {
                images = _jsonSerializer.DeserializeFromStream<List<ScheduleDirect.ShowImages>>(
                    innerResponse2.Content);
            }

            return images;
        }
        public async Task<IEnumerable<ChannelInfo>> getChannelInfo(IEnumerable<ChannelInfo> channelsInfo,
            CancellationToken cancellationToken)
        {
            var token = await GetToken(cancellationToken);

            var lineup = Plugin.Instance.Configuration.lineup;
            _channelPair = new Dictionary<string, ScheduleDirect.Station>();
            if (!String.IsNullOrWhiteSpace(token) && !String.IsNullOrWhiteSpace(lineup.Id))
            {
                    var httpOptions = new HttpRequestOptionsMod()
                    {
                        Url = _apiUrl + "/lineups/" + lineup.Id,
                        UserAgent = UserAgent,
                        Token = token,
                        CancellationToken = cancellationToken
                    };
                   
                    using (var response = await _httpClient.Get(httpOptions))
                    {
                        var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response);
                        _logger.Info("Found " + root.map.Count() + " channels on the lineup on ScheduleDirect");
                        _logger.Info("Mapping Stations to Channel");
                        foreach (ScheduleDirect.Map map in root.map)
                        {
                            var channel = (map.channel ?? (map.atscMajor + "." + map.atscMinor)).TrimStart('0');
                            _logger.Debug("Found channel: " + channel + " in Schedules Direct");
                            if (!_channelPair.ContainsKey(channel) && channel != "0.0")
                            {
                                _channelPair.Add(channel,
                                    root.stations.FirstOrDefault(item => item.stationID == map.stationID));
                            }
                        }
                        _logger.Info("Added " + _channelPair.Count() + " channels to the dictionary");
                        
                        foreach (ChannelInfo channel in channelsInfo)
                        {
                            //  Helper.logger.Info("Modifyin channel " + channel.Number);
                            if (_channelPair.ContainsKey(channel.Number))
                            {
                                string channelName;
                                if (_channelPair[channel.Number].logo != null)
                                {
                                    channel.ImageUrl = _channelPair[channel.Number].logo.URL;
                                    channel.HasImage = true;
                                }
                                if (_channelPair[channel.Number].affiliate != null)
                                {
                                    channelName = _channelPair[channel.Number].affiliate;
                                }
                                else
                                {
                                    channelName = _channelPair[channel.Number].name;
                                }
                                channel.Name = channelName;
                            }
                            else
                            {
                                _logger.Info("Schedules Direct doesnt have data for channel: " + channel.Number + " " +
                                             channel.Name);
                            }
                        }
                    }
                }
            return channelsInfo;
        }