##############################################
# $Id$

package main;
use strict;
use warnings;

sub SetExtensions($$@);
sub SetExtensionsFn($);

sub
SetExtensions($$@)
{
  my ($hash, $list, $name, $cmd, @a) = @_;

  my %se_list = (
    "on-for-timer"  => 1,
    "off-for-timer" => 1,
    "on-till"       => 1,
    "off-till"      => 1,
    "blink"         => 2,
    "intervals"     => 0,
    "toggle"        => 0
  );

  my $hasOn  = ($list =~ m/\bon\b/);
  my $hasOff = ($list =~ m/\boff\b/);
  my $value = Value($name);
  my $em = AttrVal($name, "eventMap", undef);
  if($em) {
    if(!$hasOn || !$hasOff) {
      $hasOn  = ($em =~ m/:on\b/)  if(!$hasOn);
      $hasOff = ($em =~ m/:off\b/) if(!$hasOff);
    }
    $cmd = ReplaceEventMap($name, $cmd, 1) if($cmd ne "?"); # Fix B0-for-timer
    (undef, $value) = ReplaceEventMap($name, [$name, $value], 0);
  }
  if(!$hasOn || !$hasOff) { # No extension
    return "Unknown argument $cmd, choose one of $list";
  }

  if(!defined($se_list{$cmd})) {
    # Add only "new" commands
    my @mylist = grep { $list !~ m/\b$_\b/ } keys %se_list;
    return "Unknown argument $cmd, choose one of $list " .
        join(" ", @mylist);
  }
  if($se_list{$cmd} && $se_list{$cmd} != int(@a)) {
    return "$cmd requires $se_list{$cmd} parameter";
  }

  my $cmd1 = ($cmd =~ m/on.*/ ? "on" : "off");
  my $cmd2 = ($cmd =~ m/on.*/ ? "off" : "on");
  my $param = $a[0];

  if($cmd eq "on-for-timer" || $cmd eq "off-for-timer") {
    RemoveInternalTimer("SE $name $cmd");
    return "$cmd requires a number as argument" if($param !~ m/^\d*\.?\d*$/);

    if($param) {
      DoSet($name, $cmd1);
      InternalTimer(gettimeofday()+$param,"SetExtensionsFn","SE $name $cmd",0);
    }

  } elsif($cmd eq "on-till" || $cmd eq "off-till") {
    my ($err, $hr, $min, $sec, $fn) = GetTimeSpec($param);
    return "$cmd: $err" if($err);

    my $at = $name . "_till";
    CommandDelete(undef, $at) if($defs{$at});

    my @lt = localtime;
    my $hms_till = sprintf("%02d:%02d:%02d", $hr, $min, $sec);
    my $hms_now  = sprintf("%02d:%02d:%02d", $lt[2], $lt[1], $lt[0]);
    if($hms_now ge $hms_till) {
      Log3 $hash, 4,
        "$cmd: won't switch as now ($hms_now) is later than $hms_till";
      return "";
    }
    DoSet($name, $cmd1);
    CommandDefine(undef, "$at at $hms_till set $name $cmd2");

  } elsif($cmd eq "blink") {
    my $p2 = $a[1];
    delete($hash->{SE_BLINKPARAM});
    return "$cmd requires 2 numbers as argument"
        if($param !~ m/^\d+$/ || $p2 !~ m/^\d*\d?\d*$/);

    if($param) {
      DoSet($name, "on-for-timer", $p2);
      $param--;
      if($param) {
        $hash->{SE_BLINKPARAM} = "$param $p2";
        InternalTimer(gettimeofday()+2*$p2,"SetExtensionsFn","SE $name $cmd",0);
      }
    }

  } elsif($cmd eq "intervals") {
    my $at0 = "${name}_till";
    my $at1 = "${name}_intervalFrom",
    my $at2 = "${name}_intervalNext";
    CommandDelete(undef, $at0) if($defs{$at0});
    CommandDelete(undef, $at1) if($defs{$at1});
    CommandDelete(undef, $at2) if($defs{$at2});

    my $intSpec = shift(@a);
    if($intSpec) {
      my ($from, $till) = split("-", $intSpec);

      my ($err, $hr, $min, $sec, $fn) = GetTimeSpec($from);
      return "$cmd: $err" if($err);
      my @lt = localtime;
      my $hms_from = sprintf("%02d:%02d:%02d", $hr, $min, $sec);
      my $hms_now  = sprintf("%02d:%02d:%02d", $lt[2], $lt[1], $lt[0]);

      if($hms_from le $hms_now) { # By slight delays at will schedule tomorrow.
        SetExtensions($hash, $list, $name, "on-till", $till);

      } else {
        CommandDefine(undef, "$at1 at $from set $name on-till $till");

      }

      if(@a) {
        my $rest = join(" ", @a);
        my ($from, $till) = split("-", shift @a);
        CommandDefine(undef, "$at2 at $from set $name intervals $rest");
      }
    }
    
  } elsif($cmd eq "toggle") {
    DoSet($name, $value =~ m/^on/ ? "off" : "on");

  }

  return undef;
}

sub
SetExtensionsFn($)
{
  my (undef, $name, $cmd) = split(" ", shift, 3);
  return if(!defined($defs{$name}));


  if($cmd eq "on-for-timer") {
    DoSet($name, "off");

  } elsif($cmd eq "off-for-timer") {
    DoSet($name, "on");

  } elsif($cmd eq "blink" && $defs{$name}{SE_BLINKPARAM}) {
    DoSet($name, "blink", split(" ", $defs{$name}{SE_BLINKPARAM}, 2));

  }

}

1;
