package Net::Indosoft::QSuite;

use strict;
use warnings;
use vars qw( $AUTOLOAD );
use JSON;
use Net::HTTPS::Any qw( https_post );

=head1 NAME

Net::Indosoft::QSuite - Interface to Indosoft Q-Suite API

=head1 VERSION

Version 0.01

=cut

our $VERSION = '0.01';


=head1 SYNOPSIS

    use Net::Indosoft::QSuite;

    my $qsuite = Net::Indosoft::QSuite->new(
      host        => 'server.example.com',
      gateway_key => '09ad8f6b692717316913809f9903fd08',
    );


    ###
    # Manage Tenant
    ###

    my $uuid = $qsuite->editTenant(
                                   mode            => 'create',
                                   name            => 'Tenant One',
                                   shortname       => 'one',
                                   hostname        => 'one.tenant.com',
                                   callerid_name   => 'Tenant One',
                                   callerid_number => '5551112222',
                                  )
      or die "can't create tenant: ". $qsuite->errstr;

    my $uuid = $qsuite->editTenant(
                                   mode            => 'edit',
                                   uuid            => 'Tenant UUID',
                                   name            => 'Tenant Name',
                                   shortname       => 'Tenant shortname',
                                   hostname        => 'Tenant hostname',
                                   callerid_name   => 'Nailup caller ID name',
                                   callerid_number => 'Nailup caller ID number',
                                  )
      or die "can't edit tenant: ". $qsuite->errstr;

    $qsuite->editTenant(
                         mode        => 'delete',
                         uuid        => 'Tenant UUID',
                       )
      or die "can't delete tenant: ". $qsuite->errstr;


    ###
    # Manage Trunk Assignments
    ###

    my $uuid = $qsuite->assignTrunkToTenant(
                            mode        => 'assign',
                            tenant_uuid => 'f269fa3480e739d77e4fee61f94575e2',
                            trunk_id    => '1', #provided by indosoft
               )
      or die  "can't assign trunk to tenant ". $qsuite->errstr;

    my $uuid = $qsuite->assignTrunkToTenant(
                            mode        => 'unassign',
                            tenant_uuid => 'Tenant UUID',
                            trunk_id    => 'trunk ID,     #provided by indosoft
               )
      or die  "can't trunk from tenant: ". $qsuite->errstr;


    ###
    # Manage DID
    ###

    my $number = $qsuite->editDID(
                   mode                => 'create',
                   tenant_uuid         => 'f269fa3480e739d77e4fee61f94575e2',
                   number              => '4445550011',
                   auto_attendant_uuid => 'c4367c52bf45525bfbb7614b167a5335',
                 )
      or die "can't create DID: ". $qsuite->errstr;

   
    my $number = $qsuite->editDID(
                   mode                => 'edit'
                   tenant_uuid         => 'Tenant UUID',
                   number              => 'The DID number',
                   auto_attendant_uuid => 'UUID of the assigned auto attendant',
                 )
      or die "can't edit DID: ". $qsuite->errstr;

    my $number = $qsuite->editDID(
                   mode                => 'delete'
                   tenant_uuid         => 'Tenant UUID',
                 )
      or die "can't delete DID: ". $qsuite->errstr;


    ###
    # Manage Auto Attendant
    ###

    my $uuid = $qsuite->editAutoAttendant(
                  mode                    => 'create',
                  tenant_uuid             => 'f269fa3480e739d77e4fee61f94575e2',
                  name                    => 'Auto F. Atttendant',
                  repeat_limit            => 54,
                  response_limit          => 32,
                  allow_extension_dialing => 0, # 0 or 1
               )
      or die "can't create auto attendant: ". $qsuite->errstr;

    my $uuid = $qsuite->editAutoAttendant(
                  mode                    => 'edit'
                  tenant_uuid             => 'Tenant UUID',
                  uuid                    => 'UUID of the assigned auto attendant',
                  name                    => 'Auto Attenant name',
                  repeat_limit            => 54, # The number of time to attempt to gather input
                  response_limit          => 32, # The timeout on the response
                  allow_extension_dialing => 0, # "Allow the caller to dial extensions with the menu
               )
      or die "can't edit auto attendant: ". $qsuite->errstr;

    my $uuid = $qsuite->editAutoAttendant(
                  mode                => 'delete'
                  tenant_uuid         => 'Tenant UUID',
                  uuid                => 'UUID of the assigned auto attendant',
               )
      or die "can't delete auto attendant: ". $qsuite->errstr;


    ###
    # Manage Ring Group
    ###

    my $uuid = $qsuite->editRingGroup(
                  mode            => 'create',
                  tenant_uuid     => 'f269fa3480e739d77e4fee61f94575e2',
                  #docs say uuid ('ring group uuid') for create, but prob. wrong
                  name            => 'Ring Group',
                  timeout         => 54,
                  extension_uuids => '432789473febdf00fe1ee77777777777,ab98342efabc43',
               )
      or die "can't create ring group: ". $qsuite->errstr;

    my $uuid = $qsuite->editRingGroup(
                  mode            => 'edit'
                  tenant_uuid     => 'Tenant UUID',
                  uuid            => 'Ring group UUID',
                  name            => 'Ring group name',
                  timeout         => 54, # Ring group timeout
                  extension_uuids => '1234abc,999fefefefe', # Comma-separated list of extension UUIDs that make up the ring group
               )
      or die "can't edit ring group: ". $qsuite->errstr;

    my $uuid = $qsuite->editRingGroup(
                  mode            => 'delete'
                  tenant_uuid     => 'Tenant UUID',
                  uuid            => 'Ring group UUID',
               )
      or die "can't delete ring group: ". $qsuite->errstr;


    ###
    # Manage Employee/User
    ###

    my $uuid = $qsuite->editEmployee(
                  mode        => 'create',
                  tenant_uuid => 'f269fa3480e739d77e4fee61f94575e2',
                  #docs say uuid ('employee uuid') for create, but prob. wrong
                  username    => 'tofub',
                  password    => 'beast1',
                  firstname   => 'Tofu',
                  lastname    => 'Beast',
               )
      or die "can't create employee: ". $qsuite->errstr;

    my $uuid = $qsuite->editEmployee(
                  mode        => 'edit'
                  tenant_uuid => 'Tenant UUID',
                  uuid        => 'Employee UUID',
                  username    => 'tofub',
                  password    => 'beast1',
                  firstname   => 'Tofu',
                  lastname    => 'Beast',
               )
      or die "can't edit employee: ". $qsuite->errstr;

    my $uuid = $qsuite->editEmployee(
                  mode            => 'delete'
                  tenant_uuid     => 'Tenant UUID',
                  uuid            => 'Employee UUID',
               )
      or die "can't delete employee: ". $qsuite->errstr;


    ###
    # Manage Extension
    ###

    #or does this return an "extension uuid"?  its wanted for devices...
    my $number = $qsuite->editExtension(
                   mode        => 'create',
                   tenant_uuid => 'f269fa3480e739d77e4fee61f94575e2',
                   number      => '101',
                 )
      or die "can't create extension: ". $qsuite->errstr;

    #this is documented but seems to make no sense
    #my $number = $qsuite->editExtension(
    #               mode        => 'edit'
    #               tenant_uuid => 'Tenant UUID',
    #               number      => '101',
    #             )
    #  or die "can't edit extension: ". $qsuite->errstr;

    #or does this want an "extension uuid"?
    my $number = $qsuite->editExtension(
                   mode        => 'delete'
                   tenant_uuid => 'Tenant UUID',
                   number      => '101',
                )
      or die "can't delete extension: ". $qsuite->errstr;


    ###
    # Manage Device
    ###

    my $uuid = $qsuite->editDevice(
                   mode           => 'create',
                   tenant_uuid    => 'f269fa3480e739d77e4fee61f94575e2',
                   employee_uuid  => 'f269fa3480e739d77e4fee61f94575e2',
                   extension_uuid => 'f269fa3480e739d77e4fee61f94575e2',
                   #docs say "device uuid" for create, but i doubt it
                   protocol       => 'sip', #sip iax or dahdi
                 )
      or die "can't create device: ". $qsuite->errstr;

    my $uuid = $qsuite->editDevice(
                   mode           => 'edit'
                   tenant_uuid    => 'Tenant UUID',
                   employee_uuid  => 'Employee UUID',
                   extension_uuid => 'Extension UUID',
                   uuid           => 'Device UUID',
                   protocol       => 'sip', #sip iax or dahdi
               )
      or die "can't edit device: ". $qsuite->errstr;

    #docs for required fields here appear to be on crack (tenant_uuid only?),
    # so my best guess
    my $uuid = $qsuite->editDevice(
                   mode           => 'delete'
                   #perhaps? tenant_uuid    => 'Tenant UUID',
                   #perhaps? employee_uuid  => 'Employee UUID',
                   #perhaps? extension_uuid => 'Extension UUID',
                   uuid           => 'Device UUID',
               )
      or die "can't delete device: ". $qsuite->errstr;


    ###
    # Manage Voicemail Settings
    ###

    my $uuid = $qsuite->editVoicemailSettings(
                   extension_uuid => 'f269fa3480e739d77e4fee61f94575e2',
                   pin            => '5454',
               )
      or die "can't edit voicemail: ". $qsuite->errstr;


    ###
    # Manage Extension Forwarding Settings
    ###

    my $uuid = $qsuite->editForwardingSettings(
                   #perhaps? docs say yes, exampe no tenant_uuid    => 'f269fa3480e739d77e4fee61f94575e2',
                   extension_uuid => 'f269fa3480e739d77e4fee61f94575e2',
                   number         => '555-888-2222',
               )
      or die "can't edit forwarding: ". $qsuite->errstr;


=head1 METHODS

=head2 new

Creates a new Net::Indosoft:QSuite object.  Options may be passed
as a hash reference or a flat list of names and values.

=over 4

=item host (required)

=item gateway_key - A valid API gateway key (required)

=item debug (optional)

=back

=cut

sub new {
  my $proto = shift;
  my $class = ref($proto) || $proto;
  my $self = ref($_[0]) ? shift : { @_ };
  $self->{'debug'} ||= 0;
  bless($self, $class);
}

=head2 errstr

=cut

sub errstr {
  #my $class = shift;
  #return $errstr
  #  unless ref($class) && $class->isa('Net::VoIP_Innovations');

  my $self = shift; #$class;
  $self->{errstr};
}

=head2 editTenant

=head2 assignTrunkToTenant

=head2 editDID

=head2 editAutoAttendant

=cut

#our %return = (
#  'Tenant'             => 'uuid',
#  'DID'                => 'number',
#  'AutoAttendant'      => 'uuid',
#  'RingGroup'          => 'uuid', #?  its undocumented
#  'Employee'           => 'uuid',
#  'Extension'          => 'number',
#  'Device'             => 'uuid',
#  'VoicemailSettings'  => 'uuid',
#  'ForwardingSettings' => 'uuid',
#);

sub AUTOLOAD {
  my $self = shift;
  my $opts = ref($_[0]) ? shift : { @_ };

  $AUTOLOAD =~ /(^|::)(\w+)$/ or die "unparsable AUTOLOAD: $AUTOLOAD";
  my $func = $2;
  my $path = "/cti/api/external/$func.json";

  my ( $page, $https_response, %reply_headers ) =
    https_post({ host => $self->{host},
                 port => 443,
                 path => $path,
              });

  unless ( $https_response =~ /^200/i ) {
    #this is a lower-layer communication error, so it warrants an exception
    die "Error POSTing to https://". $self->{host}. "$path : $https_response\n";
    #$self->{'errstr'} = $https_response;
    #return '';
  }

  my $response = decode_json( $page );

  #use Data::Dumper;
  #warn Dumper($response); #if $self->{debug};

  unless ( $response->{success} ) { # == 1
    $self->{errstr} = $response->{error};
    return '';
  }

  $self->{errstr} = '';

  # use %return if it gets more complicated
  if ( $func =~ /(DID|Extension)$/ ) {
    return $response->{data}{number};
  } else {
    return $response->{data}{uuid};
  }

}

=head1 AUTHOR

Ivan Kohler, C<< <ivan-indosoft at freeside.biz> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-net-indosoft-qsuite at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-Indosoft-QSuite>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Net::Indosoft::QSuite


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-Indosoft-QSuite>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/Net-Indosoft-QSuite>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/Net-Indosoft-QSuite>

=item * Search CPAN

L<http://search.cpan.org/dist/Net-Indosoft-QSuite/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 LICENSE AND COPYRIGHT

Copyright (C) 2014 Freeside Internet Services, Inc. (http://freeside.biz/)

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=head1 ADVERTISEMENT

Need a complete, open-source back-office and customer self-service solution?
The Freeside software includes support for Indosoft integration, CDR
rating, invoicing, credit card and electronic check processing, integrated
trouble ticketing, and customer signup and self-service web interfaces.

http://freeside.biz/freeside/

=cut

1;
