// UI
objref vBoxFrapCircleControls, hBoxFrapCircle,  plotShapeFrapioniCircle
// Sections affected by FRAP
objref frapCircleSections[SizeTotal*2]
// Random
objref randomFrapCircle
randomFrapCircle = new Random()

// Finds sections within a circle and sets initial FRAP concentration on them.
// $1 - X coordinate circle center
// $2 - Y coordinate circle center
// $3 - Radius of a circle
// $4 - Inital concentration of FRAP ion in bleaching area
proc setInitialCircleConcentration () {
    frapCircleSectionsSize = 0
    
    forall {
        // Find sections within a circle
        if (($1-x3d(1))^2+($2-y3d(1))^2 < $3^2) {
            frapCircleSections[frapCircleSectionsSize] = new SectionRef()
            frapCircleSectionsSize += 1
            frapion0_FRAP = $4
            frapioni(0.5) = $4
        } else  {
            frapion0_FRAP = 1
        }
    }
}

// Calculates FRAP concentration data after sumulation and writes it to the file.
// $o1 - File to print data to
proc calculateAndWriteResults() { local i, FrapIonSum, BasicFrapIonSum, cylinderVolume
    FrapIonSum = 0
    BasicFrapIonSum = 0

    if (frapCircleSectionsSize > 1) {
        for i = 0, frapCircleSectionsSize - 1 {
            frapCircleSections[i].sec {
		    
                cylinderVolume = L*PI*diam^2/4

                FrapIonSum += frapioni(0.5)*cylinderVolume
                BasicFrapIonSum += cylinderVolume
            }
        }

        // The condition implies that after bleaching, the concentration is always less than that after recovery
        if (FrapIonSum/BasicFrapIonSum < 0.999)  {
            $o1.printf("%-8.5g\t%-9.5g\t%-9.5g\t%-9.5g\n", sqrt(frapCenterX*frapCenterX+frapCenterY*frapCenterY), FrapIonSum/BasicFrapIonSum, FrapIonSum, BasicFrapIonSum)
        }
    }
}

// Runs FRAP simulation numberOfTrials times.
// Each new run position of circle is generated stochastically in -30 to 30 um range.
// $1 - Number of runs.
proc runFrapCircle() { local i localobj fileFrapCircle
    fileFrapCircle = new File()
    fileFrapCircle.aopen("Text results/CircularFrapAverage.txt")
    fileFrapCircle.printf("Distance\tFrapRatio\tFrapCon\t\tFrapBasic\n")
    
    for i = 1, $1 {
        // Set initial concentration
        setInitialCircleConcentration(frapCenterX, frapCenterY, frapRadius, initialFrapConcentration)
        // Simulate
        run()
        // Calculate concentration after simulation
        calculateAndWriteResults(fileFrapCircle)

        // Set new random center
        frapCenterX = randomFrapCircle.uniform(-30, 30) // um
        frapCenterY = randomFrapCircle.uniform(-30, 30) // um
		// frapCenterX = randomFrapCircle.uniform(-10, 10) // um
        //frapCenterY = randomFrapCircle.uniform(-10, 10) // um
    }

    fileFrapCircle.close()
}

// Sets initial UI and simulation params.
proc initParamsFrapCircle() {
    frapCenterX = 20
    frapCenterY = frapCenterX
    frapRadius = 1

    initialFrapConcentration = 0
    numberOfTrials = 1

    tstop = 10
}

// Shows FRAP Circle simulation window.
proc showFrapCircleUi() {
    hBoxFrapCircle = new HBox()
    hBoxFrapCircle.intercept(1)
    {
        vBoxFrapCircleControls = new VBox()
        vBoxFrapCircleControls.intercept(1)
        {
            xpanel("")
            xlabel("====================== Initial parameters ======================")
            xlabel("Coordinates of first bleaching area. Next ones will be generated randomly.")
            xvalue("First center X (um)","frapCenterX", 1, "", 0, 1)
            xvalue("First center Y (um)","frapCenterY", 1, "", 0, 1)
            xlabel("-------------------------------------------------------------------------------------------------------------------------")
            xlabel("Radius of bleaching area")
            xvalue("Radius (um)","frapRadius", 1, "", 0, 1)
            xlabel("-------------------------------------------------------------------------------------------------------------------------")
            xlabel("Photobleaching of area is instantaneous with initial concentration")
            xvalue("Initial concentration (normalised between 0 and 1)","initialFrapConcentration", 1, "", 0, 1)
            xlabel("========================================================== = ")
            xpanel()

            xpanel("")
            xlabel("========================== Running ==========================")
            xlabel("Number of FRAP trials for the circle activation.")
            xlabel("Each trial generets new location of bleaching between -30 and 30 um.")
            xvalue("Number of FRAP trials","numberOfTrials",1)
            xlabel("-------------------------------------------------------------------------------------------------------------------------")
            xlabel("Time of recovery aftre photobleaching")
            xvalue("Time of recovery (ms)","tstop",10)
            xlabel("-------------------------------------------------------------------------------------------------------------------------")
            xlabel("Run simulation. Results are saved to the CircularFrapAverage.txt")
            xbutton("Run FRAP ", "runFrapCircle(numberOfTrials)")
            xlabel("===========================================================")
            xpanel()
        }
        vBoxFrapCircleControls.intercept(0)
        vBoxFrapCircleControls.map("")

        removeIfExists(fast_flush_list, plotShapeFrapioniCircle)
        plotShapeFrapioniCircle = new PlotShape(0)
        fast_flush_list.append(plotShapeFrapioniCircle)
        plotShapeFrapioniCircle.size(-50,50,-50,50)
        plotShapeFrapioniCircle.view(-50, -50, 100, 100, 165, 169, 400.64, 400.32)
        plotShapeFrapioniCircle.exec_menu("Shape Plot")
        plotShapeFrapioniCircle.variable("frapioni")
        plotShapeFrapioniCircle.show(0)
        plotShapeFrapioniCircle.scale(0,1)

    }
    hBoxFrapCircle.intercept(0)
    hBoxFrapCircle.map("Frap in circle")
}

// Opens FRAP Circle simulation window.
proc FrapCircle() {
    initParamsFrapCircle()
    showFrapCircleUi()
}