#########################################################################################
# Package       HiPi::Interrupt::Base
# Description:  Interrupt Handler Base
# Created       Wed Apr 24 05:58:10 2013
# SVN Id        $Id: Base.pm 63 2016-03-15 00:45:13Z Mark Dootson $
# Copyright:    Copyright (c) 2013 Mark Dootson
# Licence:      This work is free software; you can redistribute it and/or modify it 
#               under the terms of the GNU General Public License as published by the 
#               Free Software Foundation; either version 3 of the License, or any later 
#               version.
#########################################################################################

package HiPi::Interrupt::Base;

#########################################################################################
use 5.14.0;
use strict;
use warnings;
use parent qw( HiPi::Class );
use Time::HiRes;

our $VERSION = '0.42';

__PACKAGE__->create_accessors( qw( readq writeq docontinue pollcount polltimeout pinclass ) );

sub new {
    my ($class, %params ) = @_;
    
    $params{docontinue}   = 0;
    $params{pollcount}    = 0;
    $params{polltimeout}  ||= 100;
    
    my $self = $class->SUPER::new(%params);
    return $self;
}

sub run {
    my $self = shift;
    $self->docontinue(1);
    
    #-----------------------------
    # Run Loop
    #-----------------------------
    
    while( $self->docontinue ) {
        
        # Standard Queue Check
        last unless $self->check_queue;
        
        # Loop if no interrupts
        
        $self->sleep_timeout($self->polltimeout);
    }
}

sub sleep_timeout {
    my($self, $millisecs) = @_;
    Time::HiRes::usleep( 1 + int($millisecs * 1000) );
}

sub check_queue {
    my $self = shift;
    if( defined(my $msg = $self->readq->dequeue_nb) ) {
        $self->handle_message($msg);
    }
    return $self->docontinue;
}

sub pinname_2_pinid {
    my( $self, $pinname ) = @_;
    $pinname =~ s/^GPIO//;
    return $pinname * 1;
}

sub pinid_2_pinname {
    my( $self, $pinid ) = @_;
    return 'GPIO' . $pinid;
}

sub send_interrupt_result {
    my($self, $gpiopin, $value, $timestamp) = @_;
    my $interruptmsg = {
        action    => 'interrupt',
        pinid     => $gpiopin,
        error     => 0,
        value     => $value,
        timestamp => $timestamp,
        msgtext   => '',
        pinclass  => $self->pinclass,
    };
    $self->writeq->enqueue($interruptmsg);
}

sub send_action_result {
    my($self, $action, $gpiopin, $error) = @_;
    
    my $actionmsg = {
        action    => $action,
        pinid     => $gpiopin,
        error     => ( $error ) ? 1 : 0,
        value     => '',
        timestamp => $self->get_timestamp,
        msgtext   => $error || '',
        pinclass  => $self->pinclass,
    };
    $self->writeq->enqueue($actionmsg);
}

sub get_timestamp {
    my ($secs, $msecs) = Time::HiRes::gettimeofday();
    my $timestamp = ($secs * 1000) + int($msecs / 1000);
    return( $timestamp );
}

sub handle_stop {
    my($self) = @_;
    $self->docontinue(0);
}

sub handle_message {
    my($self, $msg) = @_;
    
    $msg->{action} ||= 'undefined';
    
    if ( $msg->{action} eq 'add' ) {
        $self->handle_add($msg->{pinid});
    } elsif($msg->{action} eq 'remove' ) {
        $self->handle_remove($msg->{pinid});
    } elsif($msg->{action} eq 'stop' ) {
        $self->handle_stop();
    } elsif($msg->{action} eq 'polltimeout' ) {
        $self->polltimeout( $msg->{timeout} );
    } else {
        $self->send_action_result('error', -1, qq(Unknown message action = $msg->{action} ));
    }
}


1;
