// A simple program illustrating how to use the DinkeyChange API in Java.
// Copyright 2018 Microcosm Ltd.

import uk.microcosm.dinkeydongle.DinkeyChange;
import uk.microcosm.dinkeydongle.DinkeyChangeException;
import uk.microcosm.dinkeydongle.DongleToChange;

import java.io.*;

public class DCSample
{
    public static void main(String[] args)
    {
        String userChoice = "";
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        // Prompt the user for the DinkeyChange operation to perform
        System.out.println();
        System.out.println("1) Display information about dongles attached to this computer");
        System.out.println("2) Save diagnostic information to a file");
        System.out.println("3) Apply an update code from a file");
        System.out.println("4) Apply a short update code");
        System.out.println("5) Restore a Dinkey FD Lite dongle");
        System.out.println("6) Display this computer's machine ID");
        System.out.println("7) Download and install a temporary software key");
        System.out.println("8) Download and install a demo software key");
        System.out.print("Enter an option 1 to 8. Enter anything else to exit: ");
        try
        {
            userChoice = br.readLine();
        }
        catch (IOException e)
        {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        System.out.println();

        if (userChoice.equals("1"))
        {
            /* DinkeyChange.getDongles() - get information about dongles attached to this computer.
            This method returns an array of DongleToChange objects. You can use this method's arguments
            to control which dongles it searches for - see README.html for more information. */

            int i;
            DongleToChange[] dongles;

            try
            {   // Search for all types and models of dongle, with any product code
                dongles = DinkeyChange.getDongles(DinkeyChange.TYPE_MASK_ALL, DinkeyChange.MODEL_MASK_ALL, "");

                for (i = 0; i < dongles.length; i++)
                {
                    /* Display information about each dongle found that matched the search criteria.
                    This information is needed by DinkeyRemote to create update codes for these dongles. */

                    System.out.println((i+1) + ": Dinkey " + dongles[i].typeAsString + " " + dongles[i].modelAsString);
                    System.out.println("\tDongle Number: " + dongles[i].dongleNumber);
                    System.out.println("\tProduct Code: " + dongles[i].productCode);
                    System.out.println("\tUpdate Number: " + dongles[i].updateNumber);
                }
            }
            catch (DinkeyChangeException e)
            {
                displayError(e);
            }
        }

        else if (userChoice.equals("2"))
        {
            /* DinkeyChange.writeDiagnosticsToFile() - this method creates an encrypted DLPF file containing diagnostics
            and the parameters stored in each dongle currently attached to this computer. This file can be opened with DinkeyLook.
            This method can take a String or File argument, i.e. DinkeyChange.writeDiagnosticsToFile("out.dlpf")
            is exactly equivalent to DinkeyChange.writeDiagnosticsToFile(new File("out.dlpf")) */

            String filename = null;

            // Prompt for the name of the DLPF file to create.
            // This file's path can be absolute, or relative to the current working directory.
            // If the name does not include a ".dlpf" extension, it will automatically be added.
            System.out.print("Enter output filename: ");
            try
            {
                filename = br.readLine();
            }
            catch (IOException e)
            {
                System.err.println(e.getMessage());
            }

            try
            {   // If successful, DinkeyChange.writeDiagnosticsToFile() returns the full path to the file it created
                System.out.println("Diagnostics written to " + DinkeyChange.writeDiagnosticsToFile(new File(filename)));
            }
            catch (DinkeyChangeException e)
            {
                displayError(e);
            }
        }

        else if (userChoice.equals("3"))
        {
            /* DinkeyChange.applyUpdate(File) - this method takes a File object representing
            a secure update code file (DUCF file) and applies the code to the relevant dongle
            attached to this computer, updating the parameters stored in that dongle. */

            File f;
            String filename = null;
            String confirmationCode;

            // Prompt user for location of DUCF file.
            // The path to the file can be absolute, or relative to the current working directory
            System.out.print("Enter secure update code filename: ");
            try
            {
                filename = br.readLine();
            }
            catch (IOException e)
            {
                System.err.println(e.getMessage());
            }

            f = new File(filename);   // Create a File object representing the DUCF file
            try
            {   // If successful, DinkeyChange.applyUpdate() returns the confirmation code for this update
                confirmationCode = Integer.toHexString(DinkeyChange.applyUpdate(f));
                System.out.println("Update code successfully applied. Confirmation code is " + confirmationCode);
            }
            catch (DinkeyChangeException e)
            {
                displayError(e);
            }
        }

        else if (userChoice.equals("4"))
        {
            /* DinkeyChange.applyUpdate(String) - this method takes a short secure update code
            and applies it to the relevant dongle attached to this computer, updating the parameters
            stored in that dongle. */

            String updateCode = null;
            String confirmationCode;

            // Prompt the user for the short update code
            System.out.print("Enter update code: ");
            try
            {
                updateCode = br.readLine();
            }
            catch (IOException e)
            {
                System.err.println(e.getMessage());
            }

            try
            {   // If successful, DinkeyChange.applyUpdate() returns the confirmation code for this update
                confirmationCode = Integer.toHexString(DinkeyChange.applyUpdate(updateCode));
                System.out.println("Update code successfully applied. Confirmation code is " + confirmationCode);
            }
            catch (DinkeyChangeException e)
            {
                displayError(e);
            }
        }

        else if (userChoice.equals("5"))
        {
            // DinkeyChange.restoreDinkeyFDLite() - restore a Dinkey FD Lite dongle

            try
            {
                DinkeyChange.restoreDinkeyFDLite();
                System.out.println("Dinkey FD Lite restored successfully.");
            }
            catch (DinkeyChangeException e)
            {
                displayError(e);
            }
        }

        else if (userChoice.equals("6"))
        {
            // DinkeyChange.getMachineID() - get this computer's machine ID

            String machineIDString;

            try
            {
                machineIDString = Long.toHexString(DinkeyChange.getMachineID());
                System.out.println("The Machine ID is " + machineIDString);
            }
            catch (DinkeyChangeException e)
            {
                displayError(e);
            }
        }

        else if (userChoice.equals("7"))
        {
            // DinkeyChange.downloadTempSoftwareKey() - download and install a temporary software key

            try
            {
                DinkeyChange.downloadTempSoftwareKey();
                System.out.println("The temporary software key has been downloaded successfully.");
            }
            catch (DinkeyChangeException e)
            {
                displayError(e);
            }
        }

        else if (userChoice.equals("8"))
        {
            // DinkeyChange.downloadDemoSoftwareKey() - download and install a demo software key

            String productCode = null;

            // Prompt for the product code to use
            System.out.print("Enter product code of demo software key: ");
            try
            {
                productCode = br.readLine();
            }
            catch (IOException e)
            {
                System.err.println(e.getMessage());
            }

            try
            {
                // This examples assumes that exactly one dongle model is set in the demo template
                // If multiple models are set in the template you will need to use the second parameter to specify which model to download and install
                DinkeyChange.downloadDemoSoftwareKey(productCode, DinkeyChange.SWKEY_MODEL_DEFAULT);
                System.out.println("The demo software key has been downloaded successfully.");
            }
            catch (DinkeyChangeException e)
            {
                displayError(e);
            }
        }

        System.exit(0);

    } // End of main()


    // An example of error reporting
    // Displays descriptions for some common error codes
    static void displayError(DinkeyChangeException e)
    {
        switch (e.getError())
        {
            case 401:
                System.out.println("Error! No dongles detected that meet the search criteria!");
                break;

            case 409:
                System.out.println("Error! The dongle detected has not been programmed by DinkeyAdd.");
                break;

            case 758:
                System.out.println("Error! Cannot open the update code file specified.");
                break;

            case 759:
                System.out.println("Error! The file specified is not a valid update code file.");
                break;

            case 762:
            case 763:
            case 764:
                System.out.println("Error! Update code is not in a correct format / update code file is corrupt.");
                break;

            case 765:
                System.out.println("Error! The update code does not match any dongle attached to your machine.");
                break;

            case 766:
                System.out.println("Error! The update number for this update code is too high. You need to first enter an update code that was previously sent to you.");
                break;

            case 767:
                System.out.println("Error! You have already entered this update code.");
                break;

            case 1905:
                System.out.println("Error! There is no software key available for download.");
                break;

            case 1907:
                System.out.println("Error! The temporary software key has expired. Cannot download it.");
                break;

            case 1910:
                System.out.println("Error! The software key has already been downloaded.");
                break;

            case 1921:
                System.out.println("Error! You specified the 'default model' but there is more than one model available. You need to specify a specific dongle model.");
                break;

            case 1922:
                System.out.println("Error! The model you requested is not available.");
                break;

            case 1923:
                System.out.println("Error! The demo software key template has been disabled.");
                break;

            case 1924:
                System.out.println("Error! You have run out of demo software key activations. You need to order some more.");
                break;

            default:
                System.err.println("DinkeyChange error " + e.getError() + ":" + e.getExtendedError());
                System.err.println(e.getMessage());
        }
    }

} // End of class DCSample
