aboutsummaryrefslogblamecommitdiff
path: root/foray/ForayTableViewController.swift
blob: 6a0baa1138bfc183f5f9a40f43eaf4bc205a0ec6 (plain) (tree)
1
2
3
4
5
6
7
8
9








                                         
                                  



              
                               
                      
                         



                    

                    
                            

 





                                                  












                                                                 



                                                       
                               






                                  

                                                            


                                                                                                       








                                                                                                         













                                                                                                             

                                               
                                                                               










                                                                     
                                                


          
                                                                   
                  







                                                                                                                              

           
                                                                                                          
                                                                                                                                 
        



                                                                                    









                                                                                                       
                                                                                






                                                                                           

     



                                                                      
                                  


                                                                                                  

                                                     


                                                                                                             
                                                                        
        









                                           

                                                                                                                                                          
                                                                               



                                                                                                        



                                                                        
     









                                                                        
 
//
//  ForayTableViewController.swift
//  foray
//
//  Created by Nicholas Tay on 14/3/2022.
//

import UIKit

enum ItemType: String, Decodable {
    case item
    case quest
}

struct PenguinItem: Decodable {
    var type: ItemType
    var releaseDate: Date
    var id: String
    var name: String
}

struct YearSection {
    var year: Date
    var items: [PenguinItem]
}

class ForayTableViewCell: UITableViewCell {
    @IBOutlet weak var cellItemName: UILabel!
    @IBOutlet weak var cellItemSubtitle: UILabel!
    @IBOutlet weak var cellItemImage: UIImageView!
}

// copied from sample project
private func parseDate(_ str : String) -> Date {
    let dateFormat = DateFormatter()
    dateFormat.dateFormat = "yyyy-MM-dd"
    return dateFormat.date(from: str)!
}

private func firstDayOfYear(date: Date) -> Date {
    let calendar = Calendar.current
    let components = calendar.dateComponents([.year], from: date)
    return calendar.date(from: components)!
}

class ForayTableViewController: UITableViewController {
    
    // MARK: - Static data TEMP
    
    var items = [PenguinItem]()
    var sections = [YearSection]()
    
    // MARK: - On load
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.rowHeight = UITableView.automaticDimension
        
        // Register our custom cell
        tableView.register(ForayNewTableViewCell.self, forCellReuseIdentifier: "ForayNewTableViewCell")
        
        // Not sure if this is the right way to go about this...
        let alert = UIAlertController(title: nil, message: "Grabbing data...", preferredStyle: .alert)
        let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.style = UIActivityIndicatorView.Style.medium
        loadingIndicator.startAnimating();
        alert.view.addSubview(loadingIndicator)
        present(alert, animated: true, completion: nil)
        
        reloadApiData()
        
        dismiss(animated: false, completion: nil)
        
        // Not 100% sure what this does (the for: bit)
        self.refreshControl?.addTarget(self, action: #selector(doRefresh), for: UIControl.Event.valueChanged)
    }
    
    // Not sure why need @objc. Is it due to class private/public?
    @objc func doRefresh(sender: AnyObject) {
        reloadApiData()
    }
    
    func reloadApiData() {
        loadApiData(onComplete: { (apiItems) in
            self.items = apiItems
            self.items.sort { (lhs, rhs) in lhs.releaseDate < rhs.releaseDate }
            
            let groups = Dictionary(grouping: self.items) { (item) in
                return firstDayOfYear(date: item.releaseDate)
            }
            self.sections = groups.map { (key, values) in
                return YearSection(year: key, items: values)
            }
            // Sort the sections from oldest year to newest
            self.sections.sort { (lhs, rhs) in lhs.year < rhs.year }
            
            self.tableView.reloadData()
            self.refreshControl?.endRefreshing()
        })
    }
    
    func loadApiData(onComplete: @escaping ([PenguinItem]) -> ()) {
//        return [
//            PenguinItem(type: .item, releaseDate: parseDate("2006-05-26"), id: "mh", name: "Miners Helmet"),
//            PenguinItem(type: .item, releaseDate: parseDate("2010-05-01"), id: "it", name: "Inner Tube"),
//            PenguinItem(type: .item, releaseDate: parseDate("2009-04-24"), id: "tbg", name: "Toboggan"),
//            PenguinItem(type: .item, releaseDate: parseDate("2006-03-29"), id: "spy", name: "Spy Phone"),
//            PenguinItem(type: .item, releaseDate: parseDate("2008-11-18"), id: "bnb", name: "Black Ninja Belt"),
//            PenguinItem(type: .quest, releaseDate: parseDate("2006-05-23"), id: "cmp", name: "Case of the Missing Puffles"),
//            PenguinItem(type: .quest, releaseDate: parseDate("2009-11-16"), id: "gsm", name: "G's Secret Mission"),
//            PenguinItem(type: .quest, releaseDate: parseDate("2009-04-18"), id: "cmc", name: "Case of the Missing Coins"),
//        ]
        
        var request = URLRequest(url: URL(string: "https://users.windblume.net/~nick/upload/dummy.json")!)
        request.cachePolicy = .reloadRevalidatingCacheData // Needed otherwise default caching policy seems not to check properly
        
        // Basic auth if required
        //let authData = ("ext:PASSWORD").data(using: .utf8)!.base64EncodedString()
        //request.addValue("Basic \(authData)", forHTTPHeaderField: "Authorization")

        URLSession.shared.dataTask(with: request, completionHandler: { data, response, error -> Void in
            print("finished getting data")
            print(response!)
            
            let jsonDecoder = JSONDecoder()
            jsonDecoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
                let container = try decoder.singleValueContainer()
                let dateStr = try container.decode(String.self)
                return parseDate(dateStr)
            })
            let items = try! jsonDecoder.decode([PenguinItem].self, from: data!)
            print("json decoded")
            
            // Passing back to UI, need to do it on the main thread (I think due to async?)
            DispatchQueue.main.async {
                onComplete(items)
            }
        }).resume()
    }
    
    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // Returns number of sections for table
        return self.sections.count
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // Returns number of rows for table's section
        return self.sections[section].items.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let item = self.sections[indexPath.section].items[indexPath.row]
        
        let type: String
        let icon: UIImage
        switch item.type {
        case .item:
            type = "Item"
            icon = UIImage(named: item.id)!
        case .quest:
            type = "Quest"
            icon = UIImage(named: "spy")!
        }
        
        let cell: ForayNewTableViewCell = tableView.dequeueReusableCell(withIdentifier: "ForayNewTableViewCell", for: indexPath) as! ForayNewTableViewCell
        cell.setData(name: item.name, desc: type + "ID: " + item.id, img: icon)
        return cell
    }
    
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        let section = self.sections[section]
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy"
        return "Released in " + dateFormatter.string(from: section.year)
    }
    
    // MARK: - Navigation
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let indexPath = tableView.indexPathForSelectedRow!
        let item = self.sections[indexPath.section].items[indexPath.row]
        
        let dvc = segue.destination as! ForayDetailViewController
        dvc.selectedItem = item
    }
}