@startuml
skinparam classAttributeIconSize 0
skinparam packageStyle rectangle
skinparam dpi 50


' ==================================================
' =============== PACKAGE mhuffman =================
' ==================================================
package "fr.iutfbleau.sae.mhuffman" {

    class CanonicalCode {
        +generateCodes(codesHuffman : Map<Integer,String>) : Map<Integer,String>
        +getCode(canonicalCodes : Map<Integer,String>, value : int) : String
        +getLength(codesH : Map<Integer,String>, value : int) : int
    }

    class ComparateurCanonique {
        +compare(entree1 : Map.Entry<Integer,String>, entree2 : Map.Entry<Integer,String>) : int
    }

    class ComparateurHuffmanNode {
        +compare(a : HuffmanNode, b : HuffmanNode) : int
    }

    class FrequencyTable {
        -freqR : int[]
        -freqG : int[]
        -freqB : int[]
        +FrequencyTable()
        +computeFromImage(img : RGBImage) : void
        +getRed() : int[]
        +getGreen() : int[]
        +getBlue() : int[]
    }

    class HuffmanNode {
        -value : int
        -frequence : int
        +HuffmanNode(value : int, frequence : int)
        +HuffmanNode(left : HuffmanNode, right : HuffmanNode)
        +isLeaf() : boolean
        +getFrequence() : int
        +getValue() : int
        +toString() : String
    }

    class HuffmanTree {
        -codes : Map<Integer,String>
        +HuffmanTree(freq : int[])
        +generateCodes() : Map<Integer,String>
        +getCodes() : Map<Integer,String>
        +getRoot() : HuffmanNode
    }

    ComparateurCanonique ..|> Comparator
    ComparateurHuffmanNode ..|> Comparator

    HuffmanTree "1" *-- "1" HuffmanNode : root
    HuffmanNode "1" o-- "0..1" HuffmanNode : left
    HuffmanNode "1" o-- "0..1" HuffmanNode : right

    HuffmanTree ..> ComparateurHuffmanNode
    CanonicalCode ..> ComparateurCanonique
}

' ==================================================
' ================= PACKAGE mpif ===================
' ==================================================
package "fr.iutfbleau.sae.mpif" {

    class Pixel {
        -r : int
        -g : int
        -b : int
        +Pixel(red:int, green:int, blue:int)
        +getR() : int
        +getG() : int
        +getB() : int
        +setR(r:int) : void
        +setG(g:int) : void
        +setB(b:int) : void
    }

    class RGBImage {
        -width : int
        -height : int
        +RGBImage(lar:int, haut:int)
        +getWidth() : int
        +getHeight() : int
        +setPixel(x:int, y:int, p:Pixel) : void
        +getPixel(x:int, y:int) : Pixel
    }

    class BitOutputStream {
        -octetEnConstruction : int
        -positionBit : int
        -fluxFerme : boolean
        +BitOutputStream(fluxSortie:OutputStream)
        +writeBit(bit:int) : void
        +writeBits(valeur:int, nombreBits:int) : void
        +writeBitString(codeBinaire:String) : void
        +flush() : void
        +fermerFlux() : void
    }

    class DecodeNode {
        +value : Integer
        +DecodeNode()
        +DecodeNode(left:DecodeNode, right:DecodeNode, value:Integer)
        +isLeaf() : boolean
    }

    class PIFWriter {
        +writeTOFile(filepath:String,image:RGBImage,canonR:Map<Integer,String>,canonG:Map<Integer,String>,canonB:Map<Integer,String>) : void
        +writeHeader(out:BitOutputStream, width:int, height:int) : void
        +writeTables(out:BitOutputStream,canonR:Map<Integer,String>,canonG:Map<Integer,String>,canonB:Map<Integer,String>) : void
        +encodePixels(out:BitOutputStream,image:RGBImage,canonRED:Map<Integer,String>,canonGREEN:Map<Integer,String>,canonBLUE:Map<Integer,String>) : void
    }

    RGBImage "1" *-- "*" Pixel : pixels
    DecodeNode "1" o-- "0..1" DecodeNode : left
    DecodeNode "1" o-- "0..1" DecodeNode : right

    PIFWriter ..> RGBImage
    PIFWriter ..> BitOutputStream
    BitOutputStream --> OutputStream


    FrequencyTable ..> RGBImage

}

' ==================================================
' ================= PACKAGE sae ====================
' ==================================================
package "fr.iutfbleau.sae" {

    class JPanel
    class JFrame
    interface ActionListener{
        +actionPerformed(e : ActionEvent) : void
    }
    class ConverterController {
        -abrHuffmanR : Map<Integer,String>
        -abrHuffmanG : Map<Integer,String>
        -abrHuffmanB : Map<Integer,String>
        -canonRED : Map<Integer,String>
        -canonGREEN : Map<Integer,String>
        -canonBLUE : Map<Integer,String>
        -outputPath : String
        -inputPath : String
        +ConverterController(fen:ConverterWindow, in:String, out:String)
        +loadImage(file:File) : void
        +computeFrequencies() : void
        +computeHuffman() : void
        +computeCanonical() : void
        +saveAsPIF(pathfile:String) : void
        +saveViaBtn() : void
        +conversionProcess() : void
        +getImage() : RGBImage
    }

    class ConverterWindow {
        -bottomPanel : JPanel
        +ConverterWindow()
        +setImagePreview(img:BufferedImage) : void
        +setFrequencyTable(freqR:int[], freqG:int[], freqB:int[]) : void
        +setHuffmanTable(r:Map<Integer,String>, g:Map<Integer,String>, b:Map<Integer,String>) : void
        +setCanonicalTable(r:Map<Integer,String>, g:Map<Integer,String>, b:Map<Integer,String>) : void
        +addSaveButton(controller:ConverterController) : void
        +removeSaveButton() : void
    }

    class CodeTablePanel{
        -textHuffRouge : JTextArea
        -textHuffVert : JTextArea
        -textHuffBleu : JTextArea
        -textCanonRouge : JTextArea
        -textCanonVert : JTextArea
        -textCanonBleu : JTextArea
        +CodeTablePanel()
        +creerZoneTexte(titre : String) : JTextArea
        +updatesCodes(rouge : Map<Integer,String> , vert : Map<Integer,String> , bleu : Map<Integer,String>) : void
        +updateCanonicalCodes(rouge : Map<Integer,String> , vert : Map<Integer,String> , bleu : Map<Integer,String>) : void
        +mettreAJourZoneTexte(zone : JTextArea , codes : Map<Integer,String>) : void
    }
    class FrequencyTablePanel{
        -freqRouge : JTextArea
        -freqVert : JTextArea
        -freqBleu : JTextArea
        +FrequencyTablePAnel()
        +creationZoneText(titre : String) : JTextArea
        +updateFrequencies(freqR : int[] , freqG : int[] , freqB : int[])

    }
    class ImagePreviewPanel{
        -image : BufferedImage
        -MAX_WIDTH : int = 800 {static}
        -MAX_HEIGHT : int = 600 {static}
        +ImagePreviewPanel()
        +setImage(img : BufferedImage) : void

    }

    class ExportButtonListener {
        +ExportButtonListener(controller:ConverterController)
        +actionPerformed(e:ActionEvent) : void
    }

    class ThreadSauvegardePIF {
        -fichier : File
        +ThreadSauvegardePIF(controleur:ConverterController, fichier:File)
        +run() : void
    }

    class Convertisseur {
        +main(args:String[]) : void
    }

    class GestionErreur {
        +afficherErreur(message:String) : void {static}
        +afficherInfo(message:String) : void {static}
    }

    Convertisseur --> ConverterWindow
    Convertisseur --> ConverterController

    ConverterController "1" --> "1" RGBImage : image
    ConverterController "1" --> "1" FrequencyTable : frequencyTable
    ConverterController "1" --> "1" ConverterWindow : fen

    ConverterWindow *-- CodeTablePanel
    ConverterWindow *-- FrequencyTablePanel
    ConverterWindow *-- ImagePreviewPanel

    ExportButtonListener --> ConverterController
    ThreadSauvegardePIF --> ConverterController

    CodeTablePanel --|> JPanel
    FrequencyTablePanel --|> JPanel
    ImagePreviewPanel --|> JPanel

    ConverterWindow --|> JFrame


    ExportButtonListener ..|> ActionListener

}

@enduml
