/*
 *****************************************************************************
 *                                                                           *
 *              IMPINJ CONFIDENTIAL AND PROPRIETARY                          *
 *                                                                           *
 * This source code is the sole property of Impinj, Inc. Reproduction or     *
 * utilization of this source code in whole or in part is forbidden without  *
 * the prior written consent of Impinj, Inc.                                 *
 *                                                                           *
 * (c) Copyright Impinj, Inc. 2014. All rights reserved.                     *
 *                                                                           *
 *****************************************************************************/
package com.impinj.stpexamples;

import com.impinj.stp.*;
import com.impinj.stp.Helpers;
import com.impinj.stp.StpApi.*;
import java.util.*;

public class CartonContents {

    final static String DEVICE_NAME = "SpeedwayR-XX-XX-XX";    // Please edit
    final boolean debug = false;
    Device device;

    public CartonContents(String devStr) {
        try {
            System.out.println("Carton Contents sample app");
            System.out.println();
            // Open network connection
            device = new Device(devStr, 5000);  // Allow 5 second timeout
            device.setDebug(debug);
             // setup event listeners
            //    DebugStreamGrabber dsg = new DebugStreamGrabber(devStr, DebugStreamGrabber.StreamType.RDD);
            //    dsg.startPumperThread("CartonContents.rdd");
            device.addCartonContentsReportListener(new MyCartonContentsReportListener());
            device.addTagOperationReportListener(new MyTagOperationReportListener());
            device.addDeviceEventReportListener(new MyDeviceEventReportListener());
            // Setup Device parameters
            device.runSetDeviceConfigCommand(SetDeviceConfigCommand.newBuilder()
                    .setDeviceConfig(
                            DeviceConfig.newBuilder()
                            .setDeviceMode(DeviceMode.DEVICE_MODE_ITEM_VERIFY)
                            .setOperationMode(OperationMode.OPERATION_MODE_CONTINUOUS)
                            .setReportConfig(
                                    ReportConfig.newBuilder()
                                    .setDeviceEventConfig(
                                            DeviceEventConfig.newBuilder()
                                            .setEnableGPIEvents(true)
                                    )
                            )
                            .setGPIConfig(
                                    GPIConfig.newBuilder()
                                    .setSignalingMode(GPIOSignalMode.GPIO_SIGNAL_MODE_PRESENCE_DETECTION)
                                    .setGPI1Polarity(GPIOPolarity.GPIO_POLARITY_ACTIVE_HIGH)
                                    .setGPI2Polarity(GPIOPolarity.GPIO_POLARITY_ACTIVE_HIGH)
                                    .setGPI3Polarity(GPIOPolarity.GPIO_POLARITY_ACTIVE_HIGH)
                            )
                    ).build()
            );

            // Setup Antenna parameters
            device.runSetAntennaConfigCommand(
                    SetAntennaConfigCommand.newBuilder()
                    .setAntennasConfig(
                            AntennasConfig.newBuilder()
                            .addAntennaConfig(antennaConfigFactory(1,
                                    Gen2Mode.GEN2_MODE_MAX_THROUGHPUT,
                                    InventorySearchMode.INVENTORY_SEARCH_MODE_CARTON_STAGE_1))
                            .addAntennaConfig(antennaConfigFactory(1,
                                    Gen2Mode.GEN2_MODE_MAX_THROUGHPUT_M4,
                                    InventorySearchMode.INVENTORY_SEARCH_MODE_CARTON_STAGE_2))
                            .addAntennaConfig(antennaConfigFactory(2,
                                    Gen2Mode.GEN2_MODE_MAX_THROUGHPUT,
                                    InventorySearchMode.INVENTORY_SEARCH_MODE_CARTON_STAGE_1))
                            .addAntennaConfig(antennaConfigFactory(2,
                                    Gen2Mode.GEN2_MODE_MAX_THROUGHPUT_M4,
                                    InventorySearchMode.INVENTORY_SEARCH_MODE_CARTON_STAGE_2))
                    ).build()
            );
            // Configure according to test track specification
            device.runSetCartonContentsJobCommand(
                    SetCartonContentsJobCommand.newBuilder()
                    .setCartonContentsJob(
                            CartonContentsJob.newBuilder()
                            .setEnterTriggerOffset(2060) // Enter trigger = 1.5 x center to center carton pitch  in mm -->
                            .setExitTriggerOffset(2060) // Exit trigger = 1.5 x center to center carton pitch in mm -->
                            .setCartonVelocity(762) //150 feet per minute, in mm/S -->
                    ).build()
            );

            device.engage();

            System.out.println("Press any key to quit.");
            byte buf[] = new byte[1];
            boolean started = false;
            System.out.println("Enter: 's' to start, 'q' to quit");
            while (buf[0] != 'q') {
                System.in.read(buf);
                switch (buf[0]) {
                    case 's':
                        device.start();
                        System.out.println("Entering...");
                        System.out.println("Enter: 'e' to stop, 'q' to quit");
                        started = true;
                        break;
                    case 'e':
                        device.stop();
                        System.out.println("Stopping...");
                        System.out.println("Enter: 's' to start, 'q' to quit");
                        started = false;
                        break;
                }
            }
        } catch (Exception ex) {
            System.out.println("CartonContents: " + ex.getMessage());
            ex.printStackTrace();
        } finally {
            try {
                device.stop();
                device.disengage();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            device.stpClose();
        }
    }

    private AntennaConfig antennaConfigFactory(int antennaId, Gen2Mode gen2Mode, InventorySearchMode searchMode) {
        return AntennaConfig.newBuilder()
                .setAntennaID(antennaId)
                .setGen2Mode(gen2Mode)
                .setInventorySearchMode(searchMode)
                .setGen2Session(Gen2Session.GEN2_SESSION_2)
                .setTransmitPower(2500)
                .setEnableAdaptiveTagPopulationEstimate(true).build();
    }

    public static void main(String[] args) {
        if (args.length == 1) {
            new CartonContents(args[0]);
        } else {
            new CartonContents(DEVICE_NAME);
        }
    }

    class MyCartonContentsReportListener implements Device.CartonContentsReportListener {

        public void reportEvent(CartonContentsReport report) {
            // Print a report header
            System.out.println("Carton Content Report received:\n\tStatus " + report.getCartonContentsResult()
                    + "\n\tEnter timestamp " + Helpers.getDatetimeString(report.getEnterTimestamp().getUsecondsSinceEpoch())
                    + "\n\tExit timestamp " + Helpers.getDatetimeString(report.getExitTimestamp().getUsecondsSinceEpoch()) + ".");
            System.out.println("TID\t\t\t\tEPC\t\t\t\tConfidence");
            List<CartonContentsTag> tagList = report.getCartonContentsTagList();
            for (CartonContentsTag tag : tagList) {
                System.out.println(Helpers.byteStringToString(tag.getTid()) + "\t"
                        + Helpers.byteStringToString(tag.getEpc()) + "\t"
                        + tag.getConfidence());
            }
        }
    }

    class MyTagOperationReportListener implements Device.TagOperationReportListener {

        public void reportEvent(TagOperationReport report) {
            // Very verbose
        }
    }

    class MyDeviceEventReportListener implements Device.DeviceEventReportListener {

        public void reportEvent(DeviceEventReport report) {
            if (report.hasGPIEvent()) {
                System.out.println("GPI: state=" + report.getGPIEvent().getGpiState());
            }
            if (report.hasOperationEvent()) {
                System.out.println("Operation: EventType=" + report.getOperationEvent().getOperationEventType().name());
            }
        }

    }
}
