using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
using PlexityHide.GTP;
using App.Project_WhoWhatWhen;

namespace App
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    private Project_WhoWhatWhen.Service data;
    private Project_WhoWhatWhen.Projects projects;
    private int currentProjId=-1;
    private Project_WhoWhatWhen.OneProject currentProject;
    
    private void Form1_Load(object sender, EventArgs e)
    {
      // Create a reference to the webservice
      data = new Service();
      data.Url = "http://localhost:4569/datawebserv/service.asmx";
      // Get the list of available projects and set it as DataSource for the combobox
      projects=data.GetProjects();
      projectBindingSource.DataSource = projects;
      
      // Set some current dates in the Gantt date scale
      gantt1.DateScaler.StartTime=DateTime.Today.AddDays(-5);
      gantt1.DateScaler.StopTime = DateTime.Today.AddDays(5);
      
      // Set up context menus for grid and time item area in the Gantt
      gantt1.Grid.ContextMenu = contextMenuGrid;
      gantt1.TimeItemArea.ContextMenu = contextMenuTimeItemArea;
      
      // Set some properties that will give me the look I want
      gantt1.TimeItemLinks.CreationTimeItemLinkStyle=TimeItemLinkStyle.StopToStart;
      gantt1.TimeItemLinks.CreationTimeItemLinkDrawStyle=TimeItemLinkDrawStyle.ZStyle;      
      gantt1.TimeItemLayouts[0].TimeItemStyle=TimeItemStyle.Glossy;
      

      comboBoxChooseProject_SelectedIndexChanged(null, null); // So that the first project is loaded (if any)
    }

    private void comboBoxChooseProject_SelectedIndexChanged(object sender, EventArgs e)
    {
      if (projects != null && comboBoxChooseProject.SelectedIndex!=-1)
      {
        // If any project is choosen...
        DataRow r=projects.Tables[0].Rows[comboBoxChooseProject.SelectedIndex];
        int projectid=(int)r["id"];
        
        if (projectid!=currentProjId) //...and it has changed since last time
          LoadProject(projectid); // Load the project
      }
    }
    
    private void LoadProject(int projid)
    {
      // CheckAskSave Current
      currentProjId=projid;
      currentProject=data.GetOneProject(projid);
      if (currentProject!=null)
      {

        // Set up databind for root nodes, note that currentProject.WorkNode contains
        // both root nodes and subnodes. I create a DataView to filter out the root nodes.
        // Root nodes are distinguished by their lack of foreign key value in the parentNode field.
        DataView rootview = new DataView(currentProject.WorkNode);
			  rootview.RowFilter="ISNULL(parentNode,-1)=-1 or parentNode=-1";
        gantt1.Grid.RootNodes_DataSourceList=rootview;

        // and for the time item links
        gantt1.TimeItemLinks.NameInDS_StartKey="start";
        gantt1.TimeItemLinks.NameInDS_TargetKey="target";
        gantt1.TimeItemLinks.DataSource=currentProject.WorkLinks;
      }
    
    }

    private void gantt1_OnNodeInserted(PlexityHide.GTP.Grid aGrid, PlexityHide.GTP.NodeEventArgs e)
    {
      // Node inserted, set up databind for any sub nodes
      DataRowView row = e.GridNode.ListItemWhenDataBound() as DataRowView;
      int val = (int) row["id"];

      DataView subNodeView = new DataView(currentProject.WorkNode);
      subNodeView.RowFilter = "parentNode=" + val.ToString();
      //Set the SubNodes to bind to the subNodeView
      e.GridNode.SubNodes_DataSourceList = subNodeView;
      
      
      
      
      // Add databind for time items on this row
      GanttRow gr = Gantt.GanttRowFromGridNode(e.GridNode);
      gr.Layers[0].TimeItemLayout="TimeItemLook";
      gr.Layers[0].NameInDS_Identity = "id";
      gr.Layers[0].NameInDS_Start = "start";
      gr.Layers[0].NameInDS_Stop = "stop";
      DataView subNodeView_ti = new DataView(currentProject.PlannedWork);
      subNodeView_ti.RowFilter = "node=" + val.ToString();

      gr.Layers[0].DataSourceList = subNodeView_ti;



      // Set different layout on root nodes
      if (e.GridNode.ParentNode == null)
        gantt1.Grid.CellLayouts.ApplyNamedLayoutToGridNode("Parent", e.GridNode);
      else
        gantt1.Grid.CellLayouts.ApplyNamedLayoutToGridNode("SubNode", e.GridNode);
        
      // Let the GanttRows expand on collisions (rather than making the time items thinner)
      gr.IncreaseRowHeightOnCollision=true;
      gr.IncreaseRow_SuggestedHeightPerItem=15;
      
    }


    private void menuItem1_Click(object sender, EventArgs e)
    {
      if (currentProject != null)
      {
          OneProject.WorkNodeRow row = currentProject.WorkNode.NewWorkNodeRow();
          row.parentNode = -1;
          row.description = "<new row>";
          row.project = currentProjId;

          currentProject.WorkNode.AddWorkNodeRow(row);
      }
    }

    private void menuItemAddSubWorkItem_Click(object sender, EventArgs e)
    {
      if (currentProject != null)
      {
        if (gantt1.Grid.GridStructure.FocusedCell!=null)
        {
          DataRowView r=gantt1.Grid.GridStructure.FocusedCell.Node.ListItemWhenDataBound() as DataRowView;
          if ((int)r["id"]!=0)
          {
            OneProject.WorkNodeRow row = currentProject.WorkNode.NewWorkNodeRow();
            row.parentNode = (int)r["id"];
            row.description = "<new row>";
            row.project = currentProjId;

            currentProject.WorkNode.AddWorkNodeRow(row);
          }
          else
          {
            MessageBox.Show("Cannot add sub nodes until parent is saved");
          }
        }
      }

    }

    private void menuItemDeleteWorkItem_Click(object sender, EventArgs e)
    {
      if (currentProject != null)
      {
        if (gantt1.Grid.GridStructure.FocusedCell!=null)
        {
          DataRowView r=gantt1.Grid.GridStructure.FocusedCell.Node.ListItemWhenDataBound() as DataRowView;
          r.Row.Delete();
        }
      }
    }

    private void buttonSaveProject_Click(object sender, EventArgs e)
    {
      if (currentProject!=null)
      {
        string result;
        DataSet ds=data.UpdateOneProject(currentProjId,currentProject.GetChanges(),out result);
        if (result!="")
          MessageBox.Show("Server note: "+result);
        if(ds!=null)
        {
          currentProject.Merge(ds);
          currentProject.AcceptChanges();
        }
      }      
    }

    private void menuItemAddTimeItem_Click(object sender, EventArgs e)
    {
      gantt1.EnterTimeItemCreateMode(true,null,0);
    }

    private void gantt1_OnTimeItem_AfterCreateByMouse(Gantt aGantt, TimeItemEventArgs e)
    {
      e.Allow=false; // We are databound so we just take the values and make a row of them
      
      int idForOwningNode=(int)(e.TimeItem.GanttRow.GridNode.ListItemWhenDataBound() as DataRowView)["id"];
      if (idForOwningNode>0)
      {

        OneProject.PlannedWorkRow row = currentProject.PlannedWork.NewPlannedWorkRow();
        currentProject.PlannedWork.AddPlannedWorkRow(row);
        row.followupworkamount=0;
        row.start=e.TimeItem.Start;
        row.stop=e.TimeItem.Stop;
        row.worker=-1;
        row.progress=0;
        row.node = idForOwningNode;
      }
      else
      {
        MessageBox.Show("Cannot add time items to an unsaved row");
      }
      // ok done, go back to normal mode
      gantt1.EnterTimeItemCreateMode(false, null, 0);
    }

    private void menuItemAddLink_Click(object sender, EventArgs e)
    {
      gantt1.EnterLinkCreateMode(true);
    }


    private void gantt1_OnTimeItem_LinkCreate(Gantt aGantt, TimeItemEventArgs e)
    {
      e.Allow = false; // We are databound so we just take the values and make a row of them

      int startid=(int)(e.TimeItem.ListItemWhenDataBound() as DataRowView)["id"];
      int targetid = (int)(e.LinkTargetTimeItem.ListItemWhenDataBound() as DataRowView)["id"];
      if (startid > 0 && targetid>0)
      {

        OneProject.WorkLinksRow row;
        if (e.LinkUnderEdit == null) 
        {
          // new link created
          row = currentProject.WorkLinks.NewWorkLinksRow();
          currentProject.WorkLinks.AddWorkLinksRow(row);          
        }
        else
        {
          // existing link changed(e.LinkUnderEdit) 
          row = (e.LinkUnderEdit.ListItemWhenDataBound() as DataRowView).Row as OneProject.WorkLinksRow;            
        }

        row.start=startid;
        row.target=targetid;
      }
      else
      {
        MessageBox.Show("Cannot add link if not time items are saved");
      }

      // ok done, go back to normal mode
      gantt1.EnterLinkCreateMode(false);
    }

    private void gantt1_OnTimeItem_ChangeRow(Gantt aGantt, TimeItemEventArgs e)
    {
      e.Allow=false; // Since we are databound we do not allow the Gantt to continue with the move, we change the data instead
      int idForNewNode = (int)(e.NewGanttRow.GridNode.ListItemWhenDataBound() as DataRowView)["id"];
      if (idForNewNode!=0)
      {
        // Change row is really a change of the node foreign key on the time item
        // It is actually very important to call beginEdit and endEdit here so that the row change is effectuated immediately
        (e.TimeItem.ListItemWhenDataBound() as DataRowView).BeginEdit();
        (e.TimeItem.ListItemWhenDataBound() as DataRowView)["node"] = idForNewNode;
        (e.TimeItem.ListItemWhenDataBound() as DataRowView).EndEdit();

      }
      else
      {
        MessageBox.Show("Cannot move time item to a row that is not saved (it does not have the ID value yet)");
      }           
    }

    private void menuItemDeleteTimeItem_Click(object sender, EventArgs e)
    {
      if (currentProject != null)
      {
        if (gantt1.FocusedTimeItem != null)
        {
          DataRowView r = gantt1.FocusedTimeItem.ListItemWhenDataBound() as DataRowView;
          r.Row.Delete();
        }
      }

    }

    private void menuItemDeleteLink_Click(object sender, EventArgs e)
    {
      if (currentProject != null)
      {
        if (gantt1.TimeItemLinks.SelectedLink != null)
        {
          DataRowView r = gantt1.TimeItemLinks.SelectedLink.ListItemWhenDataBound() as DataRowView;
          r.Row.Delete();
        }
      }
    }

    private void buttonPrint_Click(object sender, EventArgs e)
    {
      printPreviewDialog1.ShowDialog(this);    
    }

    int pageNo=0;
    private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
    {
      pageNo=0;
      gantt1.PrintInit(null);
    }

    private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
    {
      pageNo++;
      bool ganttHasMorePages = false;
      gantt1.PrintPage(e.Graphics, e.MarginBounds, gantt1.GridWidth, gantt1.DateScalerHeight, ref ganttHasMorePages);
      e.HasMorePages = ganttHasMorePages;
      e.MarginBounds.Inflate(10,10);
      Point p1,p4;
      p1=new Point(e.MarginBounds.Location.X,e.MarginBounds.Location.Y);
      p4 = new Point(p1.X, p1.Y);
      p4.Offset(e.MarginBounds.Width - 200, e.MarginBounds.Height);
      e.Graphics.DrawString("This is page no " + pageNo.ToString(), gantt1.Font, SystemBrushes.ControlDarkDark, p1);
      e.Graphics.DrawString("You can add all the extra info you need to the printout " , gantt1.Font, SystemBrushes.ControlDarkDark, p4);
    }

    private void printDocument1_EndPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
    {
      gantt1.PrintEnd();

    }

    private void checkBoxScheduleMode_CheckedChanged(object sender, EventArgs e)
    {
      gantt1.ScheduleMode=checkBoxScheduleMode.Checked;
    }




  }
}