using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using C1.Silverlight;
using C1.Silverlight.FlexGrid;

namespace DragCells
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            // ensure flex template has been loaded
            _flex.ApplyTemplate();

            // make rows tall enough to show our custom objects
            _flex.Rows.DefaultSize = 50;

            // no editing
            _flex.IsReadOnly = true;

            // create unbound rows and columns
            for (int r = 0; r < 50; r++)
            {
                _flex.Rows.Add(new Row());
            }
            for (int c = 0; c < 10; c++)
            {
                _flex.Columns.Add(new Column());
            }

            // create objects (model) and assign them to grid cells
            for (int r = 0; r < _flex.Rows.Count; r++)
            {
                for (int c = 0; c < _flex.Columns.Count; c++)
                {
                    if ((r + c) % 2 == 0)
                    {
                        _flex[r, c] = new MyDataObject(r, c);
                    }
                }
            }

            // register flex as drop target
            var ddMgr = new C1DragDropManager();
            ddMgr.RegisterDropTarget(_flex, true);
            ddMgr.DragDrop += _ddMgr_DragDrop;

            // activate custom cell factory
            _flex.CellFactory = new MyCellFactory(ddMgr);
        }

        // handle user dragging a cell to a new position
        void _ddMgr_DragDrop(object source, DragDropEventArgs e)
        {
            // get view object being dragged
            var bdr = e.DragSource as Border;
            var viewObject = bdr.Child as MyViewObject;
            if (viewObject != null)
            {
                // get target cell
                var ht = _flex.HitTest(e.GetPosition(_flex));
                if (ht.CellType == CellType.Cell && ht.Row > -1 && ht.Column > -1)
                {
                    // move object to target cell 
                    var oldRange = new CellRange(bdr);
                    _flex[oldRange.Row, oldRange.Column] = null;
                    _flex[ht.Row, ht.Column] = viewObject.DataObject;

                    // and move the selection
                    _flex.Select(ht.Row, ht.Column);
                }
            }
        }
    }

    /// <summary>
    /// Some POCO object. This is the model.
    /// </summary>
    public class MyDataObject
    {
        public MyDataObject(int r, int c)
        {
            Name = string.Format("cell {0},{1}", r, c);
            Temperature = (r + c) * 20;
        }
        public string Name { get; set; }
        public int Temperature { get; set; }
    }

    /// <summary>
    /// Framework element that represents a cell. This is the view.
    /// Each cell is bound to a MyDataObject in the view.
    /// </summary>
    public class MyViewObject : StackPanel
    {
        C1FlexGrid _flex;

        public MyViewObject(C1FlexGrid flex, MyDataObject data)
        {
            _flex = flex;
            DataObject = data;

            Orientation = System.Windows.Controls.Orientation.Vertical;
            
            var tb1 = new TextBlock();
            tb1.Text = data.Name;
            tb1.HorizontalAlignment = HorizontalAlignment.Center;
            tb1.FontSize = 12;
            Children.Add(tb1);

            var tb2 = new TextBlock();
            tb2.Text = data.Temperature.ToString();
            tb2.HorizontalAlignment = HorizontalAlignment.Center;
            tb2.FontSize = 8 ;
            Children.Add(tb2);
        }
        public MyDataObject DataObject { get; set; }
    }

    /// <summary>
    /// Cell factory used to create the MyElement view objects (cells, vistualized) that 
    /// correspond to the MyDataObject model objects (actual data, permanent).
    /// </summary>
    public class MyCellFactory : CellFactory
    {
        C1DragDropManager _ddMgr;

        public MyCellFactory(C1DragDropManager ddMgr)
        {
            _ddMgr = ddMgr;
        }
        public override void CreateCellContent(C1FlexGrid grid, Border bdr, CellRange range)
        {
            // get the data object stored in the unbound grid
            var obj = grid[range.Row, range.Column] as MyDataObject;
            if (obj != null)
            {
                // create a custom view object
                var e = new MyViewObject(grid, obj);

                // assign it to the cell
                bdr.Child = e;

                // register cell border as a drag source
                _ddMgr.RegisterDragSource(bdr, DragDropEffect.Move, ModifierKeys.None);
            }
            else
            {
                base.CreateCellContent(grid, bdr, range);
            }
        }
        public override void DisposeCell(C1FlexGrid grid, CellType cellType, FrameworkElement cell)
        {
            _ddMgr.RegisterDragSource(cell, DragDropEffect.None, ModifierKeys.None);
            base.DisposeCell(grid, cellType, cell);
        }
    }
}
