using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Media.Imaging;
using Microsoft.Win32;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.Charting;
using Telerik.Windows.Documents.FormatProviders.Pdf;
using Telerik.Windows.Documents.Model;
using Telerik.Windows.Data;
using System.Collections;
using System.Windows.Markup;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

        }

        private void Export_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.DefaultExt = "*.pdf";
            dialog.Filter = "Adobe PDF Document (*.pdf)|*.pdf";

            if (dialog.ShowDialog() == true)
            {
                {
                    RadDocument document = this.CreateDocument();
                    document.LayoutMode = DocumentLayoutMode.Paged;
                    document.Measure(RadDocument.MAX_DOCUMENT_SIZE);
                    document.Arrange(new RectangleF(PointF.Empty, document.DesiredSize));

                    PdfFormatProvider provider = new PdfFormatProvider();

                    using (Stream output = dialog.OpenFile())
                    {
                        provider.Export(document, output);
                    }
                }
            }
        }

        private RadDocument CreateDocument()
        {
            RadDocument document = new RadDocument();

            this.CreateChartDocumentPart(document);
            this.CreateGridDocumentPart(document);

            return document;
        }

        private void CreateChartDocumentPart(RadDocument document)
        {
            RadChart chart = new RadChart();
            chart.BeginInit();
            chart.DefaultView.ChartArea.EnableAnimations = false;
            chart.DefaultView.ChartArea.AxisX.LabelStep = 5;
            chart.Width = 600;
            chart.Height = 400;
            SeriesMapping sm = new SeriesMapping();
            sm.ItemsSource = (this.DataContext as ExamplesDataContext).RandomProducts;

            sm.SeriesDefinition = new BarSeriesDefinition() { ShowItemLabels = false, ItemStyle = this.LayoutRoot.Resources["ExportStyle"] as Style };
            sm.ItemMappings.Add(new ItemMapping("UnitPRice", DataPointMember.YValue));
            chart.SeriesMappings.Add(sm);
            chart.EndInit();

            chart.Measure(new System.Windows.Size(chart.Width, chart.Height));
            chart.Arrange(new System.Windows.Rect(new Point(0, 0), chart.DesiredSize));

            Section section = new Section();
            Paragraph paragraph = new Paragraph();
            BitmapImage bi = new BitmapImage();
            bi.BeginInit();
            bi.CacheOption = BitmapCacheOption.OnLoad;

            MemoryStream ms = new MemoryStream();
            chart.ExportToImage(ms, new PngBitmapEncoder());
            bi.StreamSource = ms;
            bi.EndInit();

            ImageInline image = new ImageInline(new WriteableBitmap(bi)) { Width = 700, Height = 500 };
            paragraph.Inlines.Add(image);
            section.Blocks.Add(paragraph);
            document.Sections.Add(section);

            ms.Close();
        }

        private void CreateGridDocumentPart(RadDocument document)
        {
            RadGridView gridView = new RadGridView();
            gridView.BeginInit();
            gridView.Width = 600;
            gridView.Height = 400;
            gridView.AutoGenerateColumns = true;
            gridView.AutoExpandGroups = true;
            gridView.IsReadOnly = true;
            gridView.CanUserFreezeColumns = false;
            gridView.ItemsSource = (this.DataContext as ExamplesDataContext).RandomProducts;
            gridView.EndInit();

            gridView.Measure(new System.Windows.Size(gridView.Width, gridView.Height));
            gridView.Arrange(new System.Windows.Rect(new Point(0, 0), gridView.DesiredSize));

            List<GridViewBoundColumnBase> columns = (from c in gridView.Columns.OfType<GridViewBoundColumnBase>()
                                                     orderby c.DisplayIndex
                                                     select c).ToList();

            Table table = new Table();

            Section section = new Section();
            section.Blocks.Add(table);
            document.Sections.Add(section);

            if (gridView.ShowColumnHeaders)
            {
                TableRow headerRow = new TableRow();

                if (gridView.GroupDescriptors.Count() > 0)
                {
                    TableCell indentCell = new TableCell();
                    indentCell.PreferredWidth = new TableWidthUnit(gridView.GroupDescriptors.Count() * 20);
                    headerRow.Cells.Add(indentCell);
                }

                for (int i = 0; i < columns.Count(); i++)
                {
                    TableCell cell = new TableCell();
                    AddCellValue(cell, columns[i].UniqueName);
                    cell.PreferredWidth = new TableWidthUnit((float)columns[i].ActualWidth);
                    headerRow.Cells.Add(cell);
                }

                table.Rows.Add(headerRow);
            }

            if (gridView.Items.Groups != null)
            {
                for (int i = 0; i < gridView.Items.Groups.Count(); i++)
                {
                    AddGroupRow(table, gridView.Items.Groups[i] as QueryableCollectionViewGroup, columns, gridView);
                }
            }
            else
            {
                AddDataRows(table, gridView.Items, columns, gridView);
            }
        }

        private void AddDataRows(Table table, IList items, IList<GridViewBoundColumnBase> columns, RadGridView gridView)
        {
            for (int i = 0; i < items.Count; i++)
            {
                TableRow row = new TableRow();

                if (gridView.GroupDescriptors.Count() > 0)
                {
                    TableCell indentCell = new TableCell();
                    indentCell.PreferredWidth = new TableWidthUnit(gridView.GroupDescriptors.Count() * 20);
                    row.Cells.Add(indentCell);
                }

                for (int j = 0; j < columns.Count(); j++)
                {
                    TableCell cell = new TableCell();

                    object value = columns[j].GetValueForItem(items[i]);

                    AddCellValue(cell, value != null ? value.ToString() : string.Empty);

                    cell.PreferredWidth = new TableWidthUnit((float)columns[j].ActualWidth);

                    row.Cells.Add(cell);
                }

                table.Rows.Add(row);
            }
        }

        private void AddGroupRow(Table table, QueryableCollectionViewGroup group, IList<GridViewBoundColumnBase> columns, RadGridView gridView)
        {
            TableRow row = new TableRow();

            int level = GetGroupLevel(group);
            if (level > 0)
            {
                TableCell cell = new TableCell();
                cell.PreferredWidth = new TableWidthUnit(level * 20);
                row.Cells.Add(cell);
            }

            TableCell aggregatesCell = new TableCell();
            aggregatesCell.ColumnSpan = columns.Count() + (gridView.GroupDescriptors.Count() > 0 ? 1 : 0) - (level > 0 ? 1 : 0);

            AddCellValue(aggregatesCell, group.Key != null ? group.Key.ToString() : string.Empty);

            foreach (AggregateResult result in group.AggregateResults)
            {
                AddCellValue(aggregatesCell, result.FormattedValue != null ? result.FormattedValue.ToString() : string.Empty);
            }

            row.Cells.Add(aggregatesCell);

            table.Rows.Add(row);

            if (group.HasSubgroups)
            {
                for (int i = 0; i < group.Subgroups.Count(); i++)
                {
                    AddGroupRow(table, group.Subgroups[i] as QueryableCollectionViewGroup, columns, gridView);
                }
            }
            else
            {
                for (int i = 0; i < group.ItemCount; i++)
                {
                    AddDataRows(table, group.Items, columns, gridView);
                }
            }
        }

        private void AddCellValue(TableCell cell, string value)
        {
            Paragraph paragraph = new Paragraph();
            cell.Blocks.Add(paragraph);

            Span span = new Span();
            span.Text = value;

            paragraph.Inlines.Add(span);
        }

        private int GetGroupLevel(IGroup group)
        {
            int level = 0;

            IGroup parent = group.ParentGroup;

            while (parent != null)
            {
                level++;
                parent = parent.ParentGroup;
            }

            return level;
        }
    }
}
