//导入框架,所有Cocoa框架都已经封装过了
import Cocoa

//基本变量
func variableTest(){
    //在调用变量时,如果 variable?.doSomeThing()中variable为nil,则返回nil,否则展开调用返回调用结果
    //由于这个原因,在swift中应该是没有基本类型了,比如int,bool,char *等等
    var variable:Int? = 2
    variable = nil
    
    var variable2:Bool = true
    variable2 = true
    
    enum Rank: Int{
        case Ace = 1
        case Two, Three, Four, Five, Six,
        Seven,
        Eight, Nine, Ten
        case Jack, Queen, King
        
        func description()->String{
            switch self{
            case .Ace:
                return "ace"
            case .Jack:
                return "Jack"
            case .King:
                return "King"
            case .Queen:
                return "Queen"
            default:
                return String (self.toRaw())
            }
        }
    }
    
    let ace = Rank.Ace
    let aceRawValue = ace.toRaw()
    ace.description()
    
    if let convertedRank = Rank.fromRaw(3){
        let threeDescription = convertedRank.description()
    }
}
variableTest();


//自定义类型
func selfDefinitionTypeTest(){
    var str = "Hello, playground"
    var equivalentEmptyArray = Array<Int>()
    equivalentEmptyArray += 4;
    
    struct MyType: Printable {
        var name = "Untitled"
        var description: String {  //默认的描述函数,打印的时候用
        return "MyType: \(name)"
        }
    }
    let value = MyType()
    println("Created a \(value)")
    
    struct MyType2: DebugPrintable {
        var name = "Untitled"
        var debugDescription: String {
        return "MyType: \(name)"
        }
    }
    let value2 = MyType2()
}
selfDefinitionTypeTest();


//元组,C++ 中std::tuple<T>, python内核类型
func tupleTest(){
    func tuple() -> (Double, Double, Double){
        return (5, 2, 7);
    }
    //这样接收返回值的
    var (a,b,c) = tuple()
    a
    b
    c
    //也可以这样,然后用数字索引
    var ret = tuple()
    ret.0
    ret.1
    ret.2
}
tupleTest();


//模板测试
func templateTest(){
    struct TmpVar<T>{
        var integer = 2
        var string = "let's have a talk"
        init(var integer:Int){
            self.integer = integer
        }
    }
    
    func mySort< T > (var array:Array<TmpVar<T>>) -> Array<TmpVar<T>>{
        for x in 0 .. array.count-1 {
            if array[x].integer > array[x+1].integer {
                swap(&array[x], &array[x+1])
            }
        }
        return array
    }
    
    var myArray = [TmpVar<Int>(integer: 3), TmpVar(integer:102), TmpVar(integer:100)]
    var anotherArray = mySort(myArray)
    for x in anotherArray {
        print(x.integer)
    }
}
templateTest();


func ffpTest(){
    //函数式编程,
    //函数内嵌函数,改变外部值
    func returnFifteen() -> Int{
        var y = 10
        func add5(){
            y += 5
        }
        add5()
        return y
    }
    returnFifteen()
    
    func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
        func stepForward(input: Int) -> Int { return input + 1 }
        func stepBackward(input: Int) -> Int { return input - 1 }
        return backwards ? stepBackward : stepForward
    }
    var currentValue = -4
    let moveNearerToZero = chooseStepFunction(currentValue > 0)
    // moveNearerToZero now refers to the nested stepForward() function
    while currentValue != 0 {
        println("\(currentValue) ")
        currentValue = moveNearerToZero(currentValue)
    }
    println("zero!")
    //摘录来自: Apple Inc. “The Swift Programming Language”。 iBooks. https://itun.es/us/jEUH0.l
    
    //函数返回函数
    func makeIncrementer() ->
        Double->Int{  //实际上是(Double)->Int,也就是一个函数
        func addOne(number:Double)->Int{
            return 1 + Int(number);
        }
        return addOne;
    }
    
    var increment = makeIncrementer()
    increment(7.0);
    
    func closuerTest(){
        var list:Int[] = [1,2,3]
        func hasAnyMatched(#list:Int[],  //#符号表示这个表量和外部的变量是同一个变量
            var/*表示函数内部可以改变这个值,没有var相当于const*/
            Condition/*第二参数名*/ condition:Int->Bool) -> Bool{
            for item in list{
                if condition(item){
                    return true;
                }
            }
            return false
        }
        
        var numbers = [20, 19, 7, 12]
        var condition = { number in number < 10}
        var match = hasAnyMatched(numbers, condition)
        match
        
        numbers.map({
            (number:Int)->Int in
            return 3*number
            })
        //闭包的类型已知,不用给出参数类型,返回类型,简化版:
        var mappedValue = numbers.map({number in number+3})
        mappedValue
        numbers
    }
    closuerTest();
}
ffpTest();


//扩展类型
//
protocol定义和扩展只能放在全局文件中
protocol Nothing{
}
extension Int{
    var simpleDescription:String{
        return "The number \(self)"
    }
    mutating func adjust(){
        self += 42
    }
}

func extensionTest(){
    var number = 7
    number.adjust()
    number.simpleDescription
}
extensionTest();


//In-Out Parameters
func In_Out_Parameters(){
    func swapTwoInts(inout a: Int, inout b: Int) {
        let temporaryA = a
        a = b
        b = temporaryA
    }
    
    var someInt = 3
    var anotherInt = 5
    
    swapTwoInts(&someInt, &anotherInt)
    someInt
    anotherInt
}
In_Out_Parameters();


//闭包
/*

Closure expression syntax has the following general form:

{ (parameters) -> return type in
    statements
}
*/
func ClosureTest(){
    var names = ["He", "Qinglong"]
    //传入一个闭包作为排序的条件函数
    var reversed = sort(names,  { (s1: String, s2: String) -> Bool in return s1 > s2 } )
    
    //由于sort的输入参数中,第一个参数的类型可以推导,所以闭包的参数类型也可以被推导出来,因此可以简写为:
    reversed = sort(names, {s1, s2 in return s1 < s2})
    
    //更进一步,隐式的返回类型
    reversed = sort(names, {s1, s2 in s1 < s2})
    
    /*Swift automatically provides shorthand argument names to inline closures,
    which can be used to refer to the values of the closure’s arguments 
    by the names $0, $1, $2, and so on.
    
*/
    reversed = sort(names, {$0 > $1})
    
    //尾随形式
    reversed = sort(names){ $0 > $1}
    //Here, $0 and $1 refer to the closure’s first and second String arguments
    
    /*Swift’s String type defines its string-specific implementation of the greater-than
    operator (>) as a function that has two parameters of type String,
    and returns a value of type Bool
    
*/
    reversed = sort(names, >)
    
    
    //尾随形式的解释:
    func someFunctionThatTakesAClosure(closure: () -> ()) {
        // function body goes here
    }
    
    // here's how you call this function without using a trailing closure:
    someFunctionThatTakesAClosure({
        // closure's body goes here
        })
    
    // here's how you call this function with a trailing closure instead:
    someFunctionThatTakesAClosure() {
        // trailing closure's body goes here
    }
    
    let digitNames = [
        0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",
        5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine" ]
    let numbers = [16, 58, 510]
    
    let strings = numbers.map {
        (var number) -> String in
        var output = ""
        while number > 0 {
            output = digitNames[number % 10]! + output
            number /= 10
        }
        return output
    }
    strings
    // strings is inferred to be of type String[]
    // its value is ["OneSix", "FiveEight", "FiveOneZero"]
    
    
    //返回函数的函数
    func makeIncrementor(forIncrement amount: Int) -> () -> Int {
        var runningTotal = 0
        func incrementor() -> Int {
            runningTotal += amount
            return runningTotal
        }
        return incrementor
    }
}
ClosureTest();


//Type Methods,静态成员函数
func typeMethodsTest(){
    //在类里面使用class声明静态成员方法
    class SomeClass {
        var xx:Int = 0  //目前为止,没有实现类的静态成员变量
        class func someTypeMethod() {
            // type method implementation goes here
        }
    }
    SomeClass.someTypeMethod()
    //在结构体里面使用static声明静态成员方法 和 静态成员变量
    struct LevelTracker {
        static var highestUnlockedLevel = 1
        static func unlockLevel(level: Int) {
            if level > highestUnlockedLevel { highestUnlockedLevel = level }
        }
        static func levelIsUnlocked(level: Int) -> Bool {
            return level <= highestUnlockedLevel
        }
        var currentLevel = 1
        mutating func advanceToLevel(level: Int) -> Bool {
            if LevelTracker.levelIsUnlocked(level) {
                currentLevel = level
                return true
            } else {
                return false
            }
        }
    }
}
typeMethodsTest();


//class inheritance
func inheritance(){
    //Base lcass
    class Vehicle {
        var numberOfWheels: Int
        var maxPassengers: Int
        func description() -> String {
            return "\(numberOfWheels) wheels; up to \(maxPassengers) passengers"
        }
        init() {
            numberOfWheels = 0
            maxPassengers = 1
        }
    }
    
    class Car: Vehicle {
        var speed: Double = 0.0
        init() {
            super.init()
            maxPassengers = 5
            numberOfWheels = 4
        }
        override func description() -> String {
            return super.description() + "; "
                + "traveling at \(speed) mph"
        }
    }
    
    let car = Car()
    println("Car: \(car.description())")
    
    
    class SpeedLimitedCar: Car {
        override var speed: Double  {
            get {
                return super.speed
            }
            set {
                super.speed = min(newValue, 40.0)
            }
        }
        func subClassFunc(){
            println("我的青春我做主")
        }
        
        init(){}  //构造函数/初始器
        deinit{}  //析构函数/析构器
    }
    var normalCar:Car = Car()
    normalCar.speed = 100;
    var limitedCar = SpeedLimitedCar()
    
    normalCar = limitedCar
////    ((SpeedLimitedCar*)normalCar).subClassFunc();  //看来不能强制转换基类到子类类型,应该和接口有关
}
inheritance();


//可选类型: ? 与 !
func optionalTest(){
    class Person {
        var residence: Residence?
        init(){}
    }
    
    class Residence {
        var numberOfRooms = 1
    }
    
    let john = Person()
    
    var xx:String?
    // ? 在residence为空的时候不会崩溃,返回的值是nil
    if let roomCount = john.residence?.numberOfRooms {
        xx = "John's residence has \(roomCount) room(s)."
    } else {
        xx = "Unable to retrieve the number of rooms."
    }
    println(xx?)
    
    // !在residence为空的时候会再这里崩溃
    // this triggers a runtime error
    let roomCount = john.residence!.numberOfRooms
    
}
optionalTest();