package kipps.org;

import kipps.basics.*;
import kipps.general.KFrameBase;
import kipps.general.KWindow;
import kipps.general.PanelFormatter;

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ListIterator;
import java.util.Vector;

/**
 * Created by iain on 25.11.18.
 *
 * This is a help window to show the current list of active alarms. It does not directly allow editing (this is done via the calendar windows)
 * and has no filter. The inner panel is constructed as a scroll pane, so the length is unlimited.
 *
 */

public class ReminderWindow extends KFrameBase
{
  private KError interror = new KError("Reminder panel");
  private static final long serialVersionUID = 1L;
  private ContextWrapper cw;                     // The context, for dialogues initiated from this class
  private AlarmDetailPanel tdw;                   // The panel containing detail information for the alarms
  private ContentManTodo tdFilter;               // The filter manager for the list to be displayed
  private WindowControl wc ;                     // Local reference to the window controller

  private int[] defaultSize = {250, 250, 600, 700};

// Since the menu is a constant feature of the window, it is always the same and can therefore be created on window initialisation. The
// window specifies an explicit handler for the close operation (click on close). This handler is a nested class of this class
// (MainExitListener), and this calls the same exit method as is referenced by the "Exit" item of the menu.

  public ReminderWindow ( WindowControl wcIn )
  {
    super ( wcIn );
    wc = wcIn ;
    makeMenu();                                                              // Context wrapper and dialogue controller must be set before this call
    setTitle(KSD.params.getSoftwareName() + " " + KSD.params.getSoftwareVersion() + " - Reminder List");            // Set title

    tdw = new AlarmDetailPanel ( ) ;


    JScrollPane alarmScroll = new JScrollPane(tdw,
                                              ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                                              ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);                      // Create a scroll panel to contain the details


    getContentPane().add(alarmScroll);                                    // Set up the completed frame, do not display (controller does that)
//    getContentPane ( ).add ( todoScroll ) ;                                    // Set up the completed frame, do not display (controller does that)

    return;
  }


// Standard methods required for integration with window management

  public int getWNumber()
  {
    return WindowControl.ALARM_WINDOW;
  }

  public int[] getDefaultBounds()
  {
    return defaultSize;
  }

  public int wintype ( )
  {
    return WindowControl.WIN_FRAME ;
  }

  public int getAuxConfig(int which)
  {
    return 0;
  }

// Change responder. We respond to changes in the event status.

  public void changeResponder(int eventCode, Object recSelect)
  {
    switch (eventCode)
    {
      case OrgDC.ECC_ALARM_EVENT :
      case OrgDC.ECC_DATA_RELOADED :

        tdw.updatePanel ( ) ;
        break ;
    }

    return;
  }

// Initialise the window menus and attach the menu bar to window.

  private void makeMenu ( )
  {
    KMenuItem tempItem;
    JMenu[] menus = new JMenu[1] ;                               // One window-specific menu

// View menu, for switch to other windows

    JMenu tempMenu = new JMenu (KL.gtd ( "View" , "Fenster" ) ) ;

    tempItem = new KMenuItem ( KL.gtd ( "Show contact list" , "Kontakteliste anzeigen" ) , OrgDC.SHOW_CONTACTS, dialogueControl, cw);
    tempMenu.add(tempItem);
    tempItem = new KMenuItem ( KL.gtd ( "Show calendar"       , "Kalender anzeigen" )  , OrgDC.SHOW_CALENDAR, dialogueControl, cw);
    tempMenu.add(tempItem);
    tempItem = new KMenuItem ( KL.gtd ( "Show action list"    , "Aktionsliste anzeigen" ) , OrgDC.SHOW_TODOLIST, dialogueControl, cw);
    tempMenu.add(tempItem);

    menus[0] = tempMenu ;

// *************** Create menu bar

    setJMenuBar ( initmenu ( null , menus , cw , this ) ) ;
    return ;
  }

  private class AlarmDetailPanel extends JPanel
  {
    int[] colpos = { 5 , 30 , 150 , 300 } ;

    private AlarmDetailPanel()
    {
      super();
      setBackground ( PanelFormatter.backColour ) ;                        // Set general panel appearance parameters
      setForeground ( PanelFormatter.foreColour ) ;
      setFont ( PanelFormatter.textfont ) ;                                // Set standard font

      KLayout2 detailLayout = new KLayout2 ( colpos, -1 ) ;               // New layout for reminder display
      PanelFormatter pf = new PanelFormatter ( detailLayout , null , dialogueControl , cw ) ;
      fillPanel ( detailLayout, pf ) ;
      return ;
    }

// Set up the reminder display with a list of all reminders that are due (reminder time lies in the past).
// The information always relates to the current time.

    private void fillPanel (KLayout2 detailLayout, PanelFormatter pf)
    {
      boolean hasFiredAlarms = false ;
      KDateTime now = new KDateTime();

      detailLayout.newLine ( -1 , 20 ) ;
      pf.addHeading ( KL.gtd ( "Reminder overview" , "Erinnerungen" ) , 1 ) ;

      detailLayout.newLine ( -1 , 20 ) ;

      Ico nextRem = new Ico ( ) ;

      boolean notHeaded = true ;

      int cntalarm = 0 ;

      if ( ! wc.alarmsDone.isEmpty() )                            // There are due reminders
      {
        hasFiredAlarms = true ;
        KDateTime eventT = null ;                                                         // Ursache time for the alarm
        pf.addSLSubheading(KL.gtd ( "Due reminders", "Fällige Erinnerungen"), 2 );
        detailLayout.newLine();
        ListIterator<PimAlarmManager.PimFiredAlarm> pli = wc.alarmsDone.listIterator() ;
        while ( pli.hasNext ( ) )
        {
          PimAlarmManager.PimFiredAlarm pfa = pli.next ( ) ;
          if  ( pfa.alarmType.equals("CAL") )
          {
            PimEvent event = KSD.eventList.find(PimEvent.PKEY, pfa.idUrsache);
            if (event != null)
            {
              if (event.repeater == null)
              {
                eventT = new KDateTime(event.startTime);                               // Event start time, single event
              }
              else
              {
                KDateTime testtime = new KDateTime(pfa.alarmTime);                 // This is because the reminder Vorlauf could be zero. Then we might otherwise
                testtime.add(KDateTime.MINUTE, -1);                             // get the event AFTER the one we want
                KDateTime nextT = event.repeater.nextTimeAfter(testtime);
                if (nextT != null)
                {
                  eventT = new KDateTime ( nextT ) ;
                }
              }
            }
          }
          else
          {
            eventT = pfa.alarmTime ;                                                // Not actually used in this case
          }
          if ( eventT != null )                                                     // Don't show if no valid time
          {
            pf.addButton(pfa.alarmTime.dateTimeString(), pfa.alarmType.equals("CAL") ? OrgDC.SELECT_DAY : OrgDC.SHOW_TODOLIST, "cal", eventT , 1);
            pf.addSingleText(pfa.alarmHeading, 2);
            detailLayout.newLine();
          }
        }
      }

// Any alarm found in the alarm list must be in the future. Fired alarms have been removed from the alarm list on startup.

      PimAlarm reminder = KSD.alarmList.start ( PimAlarm.KEY_ATIME , nextRem ) ;

      while ( reminder != null )
      {
        String ename ;                           // The name of the event as a string
        String etime = null ;                    // The time of the event as a string
        KDateTime eventT = null ;                // The time of the required event instance as a KDateTime object

        if ( reminder.alarmTime.compareDateTime( now ) > 0 )              // Alarm is in the future
        {
          if ( notHeaded )
          {
            pf.addSLSubheading( KL.gtd ( "Future reminders" , "Künftige Erinnerungen" ) , 2 ) ;
            detailLayout.newLine();
            notHeaded = false ;
          }
        }

        cntalarm ++ ;

        PimEvent event = KSD.eventList.find ( PimEvent.PKEY , reminder.idUrsache ) ;
        PimTodo todo = null ;
        if ( event == null )
        {
          todo = KSD.todoList.find ( PimTodo.PKEY, reminder.idUrsache ) ;      // Not an event, should be in action list
          if (todo == null)                                                    // Not an action, either
          {
            ename = null;                                                       // Don't output anything
          }
          else                                                                   // The reminder is for an action
          {
            ename = KL.gtd ( "Task: ", "Aufgabe: ") +
                    todo.formatShortHeading() +
                    " - " +
                    ( reminder.alarmType.equals ( "ACS" ) ? KL.gtd (" Begins on ", " Beginnt am ") : KL.gtd (" Due on ", " Fällig am ") ) +
                    todo.plannedDate.dateString() ;
 //                   todo.activationDate.dateString() ;
            eventT = new KDateTime ( todo.plannedDate ) ;
//            eventT = new KDateTime ( todo.activationDate ) ;
          }
        }
        else                                                                     // The reminder is for an event
        {
          ename = event.formatHeading() ;                                         // The reminder is for an event
          if ( event.repeater == null )
          {
            etime = dtString ( event.startTime , event.noTime ) ;
            ename += etime ;
            eventT = new KDateTime ( event.startTime ) ;
          }
          else
          {
            KDateTime testtime = new KDateTime ( reminder.alarmTime ) ;           // This is because the reminder Vorlauf could be zero. Then we might otherwise
            testtime.add ( KDateTime.MINUTE , - 1 ) ;                      // get the event AFTER the one we want
            KDateTime nextT = event.repeater.nextTimeAfter (testtime ) ;
            if ( nextT != null )
            {
              etime = dtString ( nextT , event.noTime ) ;
              eventT = new KDateTime ( nextT ) ;
              ename += etime ;
            }
            else
            {
              ename = null ;                       // Indicates don't output
            }
          }
        }

        if ( ename != null )                                      // We have a line to output
        {
          pf.addButton ( reminder.alarmTime.dateTimeString() ,
                         todo == null ? OrgDC.SHOW_CALENDAR : OrgDC.SHOW_TODOLIST,
                  "cal" ,
//                         reminder.alarmTime ,
                  eventT ,
                  1 ) ;
          pf.addSingleText (ename, 2 ) ;
          detailLayout.newLine();
        }
        reminder = KSD.alarmList.next ( nextRem ) ;
      }

      detailLayout.newLine ( -1 , 20 ) ;

      if ( hasFiredAlarms )                                            // Can't cancel future alarms
      {
        pf.addButton ( KL.gtd ( "Acknowledge all", "Alle quittieren") , OrgDC.ACK_ALARMS, "alarm", 1 ) ;
      }
      pf.addButton( KL.gtd ( "Close window" , "Fenster schliessen" ) , OrgDC.CLOSE_WINDOW , "clalarm" ,ReminderWindow.this , 3  ) ;
      detailLayout.putToPanel ( this ) ;
      return ;
    }

// Help method for formatting date and time as required for this display
    private String dtString ( KDateTime evtime , boolean noTime )
    {
      String result = KL.gtd ( " on " , " am " ) + evtime.dateString() ;
      if ( ! noTime )
      {
        result += KL.gtd ( " at " , " um " ) + evtime.timeString() ;
      }
      return result ;
    }
    private void updatePanel ( )
    {
      KLayout2 detailLayout = new KLayout2 ( colpos, -1 ) ;                       // New layout for contact detail display
      PanelFormatter pf = new PanelFormatter(detailLayout, null, dialogueControl , cw);
      fillPanel ( detailLayout, pf ) ;
      removeAll();
      detailLayout.putToPanel(this);
      revalidate();
      repaint();
      return;
    }

  }

}

// ************** End of class ReminderWindow ***************
