ConstValue.swift
	//
//  ConstValue.swift
//  WheelLotteryMachine
//
//  Created by akira ohmachi on 2021/04/02.
//
import SwiftUI
class ConstValue: ObservableObject {
    //background
    static let colorBg: Color = Color.init(red:0,green:0.613,blue:0.203)
    
    //button color
    static let colorStart: Color = Color.init(red:0.238, green:0.77, blue:0.387)
    static let colorSetting: Color = Color.init(red:0.543, green:0.77, blue:0.289)
}
	ContentView.swift
	//
//  ContentView.swift
//  WheelLotteryMachine
//
//  Created by akira ohmachi on 2021/04/02.
//
import SwiftUI
import GoogleMobileAds
struct ContentView: View {
    @EnvironmentObject var pub: PublicManager
    @State private var garaponImageName: String = "garapon001"
    @State private var garaponPointer: Int = 0
    @State private var busyFlag: Bool = false   //実行中
    @State private var destroyFlag: Bool = false
    @State private var emptyTextAlpha: Double = 0.0
    @State private var resultTextName: String = ""  //当選商品名
    //PIN input
    @State private var isInputPin = false   //trueでPIN入力ダイアログが表示される
    @State var pin: String = "" //ダイアログで入力したPIN
    //
    @State private var ballImageName: String = "ball_white"   //画像名
    @State private var ballPosition: CGPoint = CGPoint(x: 0, y: 0)
    @State private var ballAlpha: Double = 0.0
    private let ballNames: Array<String> = [
        "ball_gold",
        "ball_silver",
        "ball_purple",
        "ball_blue",
        "ball_green",
        "ball_yellow",
        "ball_red",
        "ball_white",
    ]
    struct BallPosition {
        let time: Int
        let x: Int
        let y: Int
        init(time: Int, x: Int, y: Int) {
            self.time = time
            self.x = x
            self.y = y
        }
    }
    private var ballPositions: Array<BallPosition> = [
        BallPosition(time:  95, x: 440, y: 540),
        BallPosition(time:  96, x: 457, y: 558),
        BallPosition(time:  97, x: 474, y: 589),
        BallPosition(time:  98, x: 492, y: 630),
        BallPosition(time:  99, x: 508, y: 620),
        BallPosition(time: 100, x: 527, y: 614),
        BallPosition(time: 101, x: 547, y: 616),
        BallPosition(time: 102, x: 567, y: 627),
        BallPosition(time: 103, x: 586, y: 651),
        BallPosition(time: 104, x: 601, y: 647),
        BallPosition(time: 105, x: 617, y: 650),
        BallPosition(time: 106, x: 634, y: 657),
        BallPosition(time: 107, x: 646, y: 650),
        BallPosition(time: 108, x: 657, y: 653),
        BallPosition(time: 109, x: 669, y: 665),
        BallPosition(time: 110, x: 680, y: 665),
    ]
    
    var body: some View {
        NavigationView {
            GeometryReader { bodyView in
                VStack(spacing: 0) {
                    HStack(spacing: 0) {
                        Button(action:{
                            self.garaponRotate()
                        }){
                            Text("drawLot")
                                .frame(width:bodyView.size.width / 4 * 3, height:100, alignment: .center)
                                .background(ConstValue.colorStart)
                                .foregroundColor(Color.white)
                        }
                        Rectangle().fill(Color.white).frame(width: 1,height: 100)
                        NavigationLink(destination: SettingView(),isActive: self.$pub.isSetting) {
                            Button(action:{
                                if self.pub.pin == "" {
                                    self.pin = ""
                                    self.buttonActionSetting()
                                } else {
                                    self.isInputPin = true
                                }
                            }){
                                Text("setting")
                                    .frame(width:bodyView.size.width / 4, height:100, alignment: .center)
                                    .background(ConstValue.colorSetting)
                                    .foregroundColor(Color.white)
                                TextFieldAlertView(
                                    text: $pin,
                                    isShowingAlert: $isInputPin,
                                    placeholder: "",
                                    isSecureTextEntry: false,
                                    title: "PIN",
                                    message: "Enter PIN",
                                    leftButtonTitle: "Cancel",
                                    rightButtonTitle: "OK",
                                    leftButtonAction: {
                                        self.pin = ""
                                    },
                                    rightButtonAction: {
                                        self.buttonActionSetting()
                                    }
                                )
                            }
                        }
                        .background(ConstValue.colorSetting)
                    }
                    .frame(width:bodyView.size.width, height:100)
                    Rectangle().fill(Color.white).frame(width: bodyView.size.width,height: 1)
                    ZStack(alignment: .bottom) {
                        ScrollView {
                            Text("empty")
                                .foregroundColor(Color.white)
                                .opacity(self.emptyTextAlpha)
                                .padding(10)
                            Image(self.garaponImageName)
                                .resizable()
                                .frame(width: bodyView.size.width, height: bodyView.size.width, alignment: .center)
                                .overlay (
                                    Text(self.resultTextName)
                                        .frame(width:bodyView.size.width, height:bodyView.size.width, alignment: .bottom)
                                        .foregroundColor(Color.white)
                                        .font(.title)
                                        .opacity(self.ballAlpha)
                                )
                                .overlay(
                                    Image(self.ballImageName)
                                        .resizable()
                                        .frame(width:bodyView.size.width / 20, height:bodyView.size.width / 20, alignment: .center)
                                        .position(x: bodyView.size.width * self.ballPosition.x / 900, y: bodyView.size.width * self.ballPosition.y / 900)
                                        .opacity(self.ballAlpha)
                                        .animation(.none)
                                )
                            Spacer(minLength: 150)
                        }
                        HStack(spacing: 0) {
                            Spacer(minLength: 0)
                            PublicManager.AdView().frame(maxWidth: bodyView.size.width, maxHeight: 50)
                            Spacer(minLength: 0)
                        }.background(Color(red:0.2,green:0.2,blue:0.2))
                    }
                }
                .background(ConstValue.colorBg)
                //.navigationBarTitle("")
                .navigationBarHidden(true)
            }
        }
        .navigationViewStyle(StackNavigationViewStyle())
        .onDisappear {     //アプリ終了時
            self.destroyFlag = true
        }
    }
    
    //選択肢を初期化
    private func initLotteryItems() {
        if self.pub.nameGold == ""
                && self.pub.nameSilver == ""
                && self.pub.namePurple == ""
                && self.pub.nameBlue == ""
                && self.pub.nameGreen == ""
                && self.pub.nameYellow == ""
                && self.pub.nameRed == ""
                && self.pub.nameWhite == ""
        { //initial
            self.pub.nameGold = NSLocalizedString("rank1", comment: "rank1")
            self.pub.nameSilver = NSLocalizedString("rank2", comment: "rank2")
            self.pub.namePurple = NSLocalizedString("rank3", comment: "rank3")
            self.pub.nameBlue = NSLocalizedString("rank4", comment: "rank4")
            self.pub.nameGreen = NSLocalizedString("rank5", comment: "rank5")
            self.pub.nameYellow = NSLocalizedString("rank6", comment: "rank6")
            self.pub.nameRed = NSLocalizedString("rank7", comment: "rank7")
            self.pub.nameWhite = NSLocalizedString("rank8", comment: "rank8")
            self.pub.qtyGold = "1"
            self.pub.qtySilver = "1"
            self.pub.qtyPurple = "2"
            self.pub.qtyBlue = "3"
            self.pub.qtyGreen = "10"
            self.pub.qtyYellow = "20"
            self.pub.qtyRed = "100"
            self.pub.qtyWhite = "300"
        }
    }
    
    //goto setting
    private func buttonActionSetting() {
        if self.busyFlag {
            return
        }
        if self.pin != self.pub.pin {
            self.pin = ""
            return
        }
        self.emptyTextAlpha = 0.0
        self.pin = ""
        self.initLotteryItems()
        self.pub.tmpNameGold = self.pub.nameGold
        self.pub.tmpNameSilver = self.pub.nameSilver
        self.pub.tmpNamePurple = self.pub.namePurple
        self.pub.tmpNameBlue = self.pub.nameBlue
        self.pub.tmpNameGreen = self.pub.nameGreen
        self.pub.tmpNameYellow = self.pub.nameYellow
        self.pub.tmpNameRed = self.pub.nameRed
        self.pub.tmpNameWhite = self.pub.nameWhite
        self.pub.tmpQtyGold = self.pub.qtyGold
        self.pub.tmpQtySilver = self.pub.qtySilver
        self.pub.tmpQtyPurple = self.pub.qtyPurple
        self.pub.tmpQtyBlue = self.pub.qtyBlue
        self.pub.tmpQtyGreen = self.pub.qtyGreen
        self.pub.tmpQtyYellow = self.pub.qtyYellow
        self.pub.tmpQtyRed = self.pub.qtyRed
        self.pub.tmpQtyWhite = self.pub.qtyWhite
        self.pub.tmpPin = self.pub.pin
        self.pub.isSetting = true
    }
    //start button on click
    private func garaponRotate() {
        if self.busyFlag {
            return
        }
        self.busyFlag = true
        self.initLotteryItems()
        self.resultTextName = ""
        self.ballPosition = CGPoint(x: self.ballPositions[0].x, y: self.ballPositions[0].y)
        self.ballAlpha = 0.0
        //ballを選ぶ
        let qtys: Array<Int> = [
            NumberFormatter().number(from: "0" + self.pub.qtyGold) as! Int,
            NumberFormatter().number(from: "0" + self.pub.qtySilver) as! Int,
            NumberFormatter().number(from: "0" + self.pub.qtyPurple) as! Int,
            NumberFormatter().number(from: "0" + self.pub.qtyBlue) as! Int,
            NumberFormatter().number(from: "0" + self.pub.qtyGreen) as! Int,
            NumberFormatter().number(from: "0" + self.pub.qtyYellow) as! Int,
            NumberFormatter().number(from: "0" + self.pub.qtyRed) as! Int,
            NumberFormatter().number(from: "0" + self.pub.qtyWhite) as! Int,
        ]
        var ballSum: Int = 0
        for i in 0 ..< qtys.count {
            ballSum += qtys[i]
        }
        if ballSum == 0 {    //選ぶものが無くなった
            emptyTextAlpha = 1.0
            self.busyFlag = false
            return
        }
        var remainNum: Int = Int.random(in: 0 ..< ballSum)
        var choiceColor: Int = -1
        for i in 0 ..< qtys.count {
            if qtys[i] != 0 {
                if qtys[i] < remainNum {
                    remainNum -= qtys[i]
                } else {
                    choiceColor = i     //この色に決定
                    break
                }
            }
        }
        //
        self.subtractBallNum(num: choiceColor)    //選んだballを消費する
        self.ballImageName = self.ballNames[choiceColor]
        switch choiceColor {
            case 0: self.resultTextName = self.pub.nameGold
            case 1: self.resultTextName = self.pub.nameSilver
            case 2: self.resultTextName = self.pub.namePurple
            case 3: self.resultTextName = self.pub.nameBlue
            case 4: self.resultTextName = self.pub.nameGreen
            case 5: self.resultTextName = self.pub.nameYellow
            case 6: self.resultTextName = self.pub.nameRed
            case 7: self.resultTextName = self.pub.nameWhite
            default: break
        }
        //
        self.garaponPointer = 0
        self.timeLineAnimation()
    }
    //garapon animation
    private func timeLineAnimation() {
        withAnimation {
            if self.destroyFlag {
                return
            }
            self.garaponPointer += 1
            if self.garaponPointer > 120 {
                self.busyFlag = false
                return
            }
            self.setImageName()
            self.ballMove()
            DispatchQueue.global().async {
                Thread.sleep(forTimeInterval: 0.02)
                DispatchQueue.main.sync {
                    if self.destroyFlag == false {
                        self.timeLineAnimation()
                    }
                }
            }
        }
    }
    //set garapon image
    private func setImageName() {
        self.garaponImageName = "garapon" + String(format: "%03d",self.garaponPointer)
    }
    //ball move
    private func ballMove() {
        if self.garaponPointer < 95 || self.garaponPointer > 110 {
            return
        }
        if self.garaponPointer == 95 {
            self.ballAlpha = 1.0
        }
        for i in 0 ..< self.ballPositions.count {
            if self.ballPositions[i].time == self.garaponPointer {
                self.ballPosition = CGPoint(x: self.ballPositions[i].x, y: self.ballPositions[i].y)
                break
            }
        }
    }
    
    private func subtractBallNum(num: Int) {
        switch num {
        case 0:
            let n: Int = NumberFormatter().number(from: "0" + self.pub.qtyGold) as! Int
            self.pub.qtyGold = String(n - 1)
        case 1:
            let n: Int = NumberFormatter().number(from: "0" + self.pub.qtySilver) as! Int
            self.pub.qtySilver = String(n - 1)
        case 2:
            let n: Int = NumberFormatter().number(from: "0" + self.pub.qtyPurple) as! Int
            self.pub.qtyPurple = String(n - 1)
        case 3:
            let n: Int = NumberFormatter().number(from: "0" + self.pub.qtyBlue) as! Int
            self.pub.qtyBlue = String(n - 1)
        case 4:
            let n: Int = NumberFormatter().number(from: "0" + self.pub.qtyGreen) as! Int
            self.pub.qtyGreen = String(n - 1)
        case 5:
            let n: Int = NumberFormatter().number(from: "0" + self.pub.qtyYellow) as! Int
            self.pub.qtyYellow = String(n - 1)
        case 6:
            let n: Int = NumberFormatter().number(from: "0" + self.pub.qtyRed) as! Int
            self.pub.qtyRed = String(n - 1)
        case 7:
            let n: Int = NumberFormatter().number(from: "0" + self.pub.qtyWhite) as! Int
            self.pub.qtyWhite = String(n - 1)
        default: break
        }
    }
    
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView().environmentObject(PublicManager())
        }
    }
}