package jc;

import javacard.framework.*;
import javacardx.framework.*;

public class Phone extends Applet{

	final static byte	SELECT	= (byte)0xA4;	//INS value for ISO 7816-4 SELECT command
    final static short  CREDIT_FID  = (short) 0x9103; //a creditFile FID-je
    final static short	CREDIT_LENGTH =  2;			//az egységek számát 2 bájton tároljuk
    final static byte   ISO_CLA = (byte)0x00;	//az ISO 7816-4 fájlkezelő utasítások CLA bájtja
    final static byte	PHONE_CLA	= (byte)0xAB;	//a Phone applet CLA byte-ja
    final static byte 	SET_CREDIT	= (byte)0x10;	//a SetCredit utasítás INS bájtja
    final static byte 	DEC_CREDIT	= (byte)0x20;	//a DecCredit utasítás INS bájtja
    final static byte 	START	=	0;			//nullás offszet buffer-műveletekhez
    final static short	NO_MORE_CREDITS 
    	= (short)0x9101;		//SW bájtok a "nincs több egység" esemény jelzésére

    FileSystem      fs;
	TransparentFile	creditFile;
  	boolean justSelected;
  	
    private Phone(){
 		//itt kell lefoglalni az összes szükséges memóriát
    	//így nem fogyhat el a memória futás közben

 		//az ISO fájlrendszer létrehozása
        fs = new FileSystem((byte)1);
        creditFile = new TransparentFile(CREDIT_FID,CREDIT_LENGTH);
        fs.addChildFile(creditFile);
   		creditFile.setSecurity(File.ACCESS_READ,File.ALLOW_ANY); //mindenki olvashatja
		creditFile.setSecurity(File.ACCESS_WRITE,File.ALLOW_NONE); //senki sem írhatja
	}//Phone()

    public static void install( APDU apdu ){
    	Phone phone = new Phone();
    	phone.register();
    }
    public boolean select(){
    	justSelected = true;
    	fs.reset();
        return true;
    }

    public void process(APDU apdu){
        byte[] buffer = apdu.getBuffer();
        if (buffer[ISO.OFFSET_CLA] == PHONE_CLA) {
	        switch (buffer[ISO.OFFSET_INS]){
	        	case SET_CREDIT:
					processSetCredit(apdu); break;
				case DEC_CREDIT:
					processDecCredit(apdu); break;
				default:
					ISOException.throwIt(ISO.SW_INS_NOT_SUPPORTED);
			}//switch
        }//if
        else if (buffer[ISO.OFFSET_CLA] == ISO_CLA) {
        	if ((buffer[ISO.OFFSET_INS] == SELECT) & justSelected) {
        	// most választották ki az appletünket
				processSelected();
			}else
		    //Minden más ISO-kompatibilis utasítást a FileSystem osztály kezel le
			if (!fs.process(apdu)) ISOException.throwIt(ISO.SW_INS_NOT_SUPPORTED);
		}
		else ISOException.throwIt(ISO.SW_CLA_NOT_SUPPORTED);
	}

	void processSelected(){
		justSelected = false;
	}


	void processSetCredit(APDU apdu){
		byte[] buffer = apdu.getBuffer();
		byte[] credit = creditFile.getData();
		short cr;
		if (buffer[ISO.OFFSET_P1] != 0)
			ISOException.throwIt(ISO.SW_INCORRECT_P1P2);
		if (buffer[ISO.OFFSET_P2] != 0)
			ISOException.throwIt(ISO.SW_INCORRECT_P1P2);
		if (buffer[ISO.OFFSET_LC] != CREDIT_LENGTH)
			ISOException.throwIt(ISO.SW_WRONG_LENGTH);
		apdu.setIncomingAndReceive();    //beolvassuk az adatokat
		if (tdk.ID.p_masterPIN.isValidated()){ //már megadták a Master PIN-t
			Util.arrayCopy(buffer,ISO.OFFSET_CDATA,credit,START,CREDIT_LENGTH);
			cr=Util.getShort(credit,START);
			Util.setShort(buffer,START,cr);
			apdu.setOutgoingAndSend((short)0, (byte)2);
			return;
		}
		else ISOException.throwIt(ISO.SW_CONDITIONS_NOT_SATISFIED);
	}

	void processDecCredit(APDU apdu){
		byte[] buffer = apdu.getBuffer();
		byte[] credit = creditFile.getData();
		short cr;
		if (buffer[ISO.OFFSET_P1] != 0)
			ISOException.throwIt(ISO.SW_INCORRECT_P1P2);
		if (buffer[ISO.OFFSET_P2] != 0)
			ISOException.throwIt(ISO.SW_INCORRECT_P1P2);
		if (buffer[ISO.OFFSET_LC] != 0)
			ISOException.throwIt(ISO.SW_WRONG_LENGTH);
		apdu.setIncomingAndReceive();    //beolvassuk az adatokat
		if (tdk.ID.p_userPIN.isValidated()){
			cr=Util.getShort(credit,START);
			if (cr==0) //már nincs több egység
				ISOException.throwIt(NO_MORE_CREDITS);
			else { //van még egység
				cr--;
				Util.setShort(credit,START,cr);
				Util.setShort(buffer,START,cr);
				apdu.setOutgoingAndSend((short)0, (byte)2);
				return;
			}
		}
		else ISOException.throwIt(ISO.SW_CONDITIONS_NOT_SATISFIED);
	}

}//Phone