using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using RS = ReportServer.Web.ReportService2005;
using System.Text;
using ReportServer.Web.ReportExecution;
using System.Net;


namespace ControlExplorer_Web
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class ReportsService
    {
        List<string> _whitelist = new List<string>
        {
            "Alphabetical List of Products",
            "AW Company Sales",
            "Casual Products Report",
            "Company Sales",
            "Employee Sales",
            "Employee Sales by Country",
            "Product Catalog",
            "Sales by Category",
            "Sales Order Detail",
            "Scales",
            "Suppliers",
            "Territory Sales Drilldown",
            "Thermometer",
        };

        Dictionary<string, List<ParameterDefinition>> _parametersCache = new Dictionary<string, List<ParameterDefinition>>();

        /// <summary>
        /// Method that renders a report on the server and returns a Report in the specified format (PDF or HTML).
        /// </summary>
        /// <param name="report">Name of the report to render.</param>
        /// <param name="format">Format to render the report in (PDF or HTML).</param>
        /// <param name="parameters">Parameters to use when rendering the report.</param>
        /// <returns>A Report object containing the content and parameters used to generate it.</returns>
        /// <remarks>
        /// This method uses a ReportingService2005 service found here:
        /// http://[REPORTSERVERNAME]/reportserver/reportservice2005.asmx?wsdl
        /// </remarks>
        [WebMethod]
        public Report GetReport(string report, string format, ParameterValue[] parameters)
        {
            // create reporting service
            var rs = new RS.ReportingService2005 { Credentials = CredentialCache.DefaultCredentials };
            List<ParameterDefinition> parameterDefinitions;

            // retrieve parameters for this report (from cache if possible, from server otherwise)
            if (!_parametersCache.TryGetValue(report, out parameterDefinitions))
            {
                var reportParameters = rs.GetReportParameters(report, null, true, null, null);
                parameterDefinitions = _parametersCache[report] = reportParameters
                    .Where(p => p.PromptUser && !string.IsNullOrEmpty(p.Prompt))
                    .Select(p => new ParameterDefinition
                    {
                        Name = p.Name,
                        Type = p.Type,
                        Nullable = p.Nullable,
                        AllowBlank = p.AllowBlank,
                        Prompt = p.Prompt,
                        ValidValues = p.ValidValues,
                        DefaultValues = p.DefaultValues,
                    }).ToList();
            }

            // prepare to render the report
            var re = new ReportExecutionService { Credentials = CredentialCache.DefaultCredentials };
            re.LoadReport(report, null);
            re.SetExecutionParameters(parameters, "en-us");

            // render the report
            string devInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
            string extension;
            string encoding;
            string mimeType;
            Warning[] warnings;
            string[] streamIDs;
            var result = re.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);

            // return the result
            return new Report { Data = result, Parameters = parameterDefinitions };
        }
        /// <summary>
        /// Method that retrieves a list of report definitions available on the server.
        /// </summary>
        /// <returns>A list of report definitions available on the server.</returns>
        [WebMethod]
        public List<ReportDefinition> ListReports()
        {
            var rs = new RS.ReportingService2005 { Credentials = CredentialCache.DefaultCredentials };
            var reports = new List<ReportDefinition>();
            foreach (var item in rs.ListChildren("/", true))
            {
                if (item.Type == RS.ItemTypeEnum.Report && _whitelist.Contains(item.Name))
                {
                    reports.Add(new ReportDefinition { Name = item.Name, Path = item.Path });
                }
            }
            return reports;
        }
    }
    public class ReportDefinition
    {
        public string Name { get; set; }
        public string Path { get; set; }
    }
    public class ParameterDefinition
    {
        public string Name { get; set; }
        public RS.ParameterTypeEnum Type { get; set; }
        public bool Nullable { get; set; }
        public bool AllowBlank { get; set; }
        public string Prompt { get; set; }
        public RS.ValidValue[] ValidValues { get; set; }
        [System.Xml.Serialization.XmlArrayItemAttribute("Value")]
        public string[] DefaultValues { get; set; }
    }
    public class Report
    {
        public byte[] Data { get; set; }
        public List<ParameterDefinition> Parameters { get; set; }
    }
}
