//
//  GameViewController.m
//  HighwayDash
//
//  Created by John Ryland on 8/02/2016.
//  Copyright © 2016 John Ryland. All rights reserved.
//

#import "GameViewController.h"
#import <OpenGLES/ES2/glext.h>
#include "Log.h"
#include "Debug.h"
#include "GameScreen.h"
#include "GameAudio.h"
#include "SystemInformation.h"


void LoadPlatformFile(const char* filename, std::vector<uint8_t>& data)
{
  data.clear();
  NSString *fname = [NSString stringWithUTF8String:filename];
  NSString* fileName = [fname stringByDeletingPathExtension];
  NSString* extension = [fname pathExtension];
  NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:extension];
  NSData *nsData = [NSData dataWithContentsOfFile:filePath];
  if (nsData) {
    const uint8_t* d = (const uint8_t*)[nsData bytes];
    data.assign(d, d + [nsData length]);
  } else {
    Log(LL_Error, "loader", "Couldn't load %s file", filename);
  }
}


@interface GameViewController () {
    SystemInformation m_sysInfo;
    GameScreen m_screen;
    BOOL _bannerIsVisible;
    ADBannerView *bannerView;
    GameAudioRenderer m_audio;
}
@property (nonatomic, assign) BOOL bannerIsVisible;
@property (strong, nonatomic) EAGLContext *context;
- (void)close;
@end

@implementation GameViewController

- (void)viewDidLoad
{
    if ([ADBannerView instancesRespondToSelector:@selector(initWithAdType:)]) {
      bannerView = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
    } else {
      bannerView = [[ADBannerView alloc] init];
    }
    
    /*
    //bannerView = [[ADBannerView alloc] initWithFrame:CGRectZero];
    bannerView.frame = CGRectOffset(adView.frame, 0, -50);
    bannerView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait];
    bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
*/
    
    const bool showAds = true;
    if (showAds)
    {
        bannerView.delegate=self;
        //[self.view addSubview:bannerView];
        
        //bannerView.bottomAnchor
        //bannerView.centerXAnchor
        CGRect adFrame = bannerView.frame;
        adFrame.origin.y = self.view.frame.size.height - bannerView.frame.size.height;
        adFrame.origin.x = (self.view.frame.size.width - bannerView.frame.size.width) / 2;
        bannerView.frame = adFrame;
        [self.view addSubview:bannerView];

        self.bannerIsVisible=NO;        
    }
    
    [super viewDidLoad];
    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    if (!self.context) {
        Log(LL_Error, "context", "Failed to create ES context");
    }
    GLKView *view = (GLKView *)self.view;
    view.context = self.context;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
  
    //view.preferredFramesPerSecond = 60.0;
  
    self.preferredFramesPerSecond = 62;

    Log(LL_Info, "context", "setupGL");
    [EAGLContext setCurrentContext:self.context];
    m_screen.initialize();
    
    m_audio.initialize(SampleRate_44100Hz, Bits_16, Stereo);//Mono);
    m_audio.start();
}

- (void)dealloc
{
    [self close];
}

- (void)close
{
    Log(LL_Info, "context", "tearDownGL");
    [EAGLContext setCurrentContext:self.context];
    m_screen.shutdown();
    if ([EAGLContext currentContext] == self.context) {
        [EAGLContext setCurrentContext:nil];
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    if ([self isViewLoaded] && ([[self view] window] == nil)) {
        self.view = nil;
        [self close];
        self.context = nil;
    }
    // Dispose of any resources that can be recreated.
    m_screen.freeSpace();
}

- (BOOL)prefersStatusBarHidden {
    return YES;
}

- (void)update
{
    m_screen.update(5.0f * self.timeSinceLastUpdate, fabs(self.view.bounds.size.width / self.view.bounds.size.height));
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    setDebugValue("CPU Usage:", m_sysInfo.getCpuUsage());
    setDebugValue("Memory Usage:", std::string(std::to_string(m_sysInfo.getMemoryUsage()) + " bytes").c_str());
    setDebugValue("Frame time:", std::string(std::to_string(m_sysInfo.getFrameTime() * 1000.0) + " ms").c_str());
    setDebugValue("Draw time:", std::string(std::to_string(m_sysInfo.getDrawTime() * 1000.0) + " ms").c_str());
    setDebugValue("FPS:", m_sysInfo.getFps());
    setDebugValue("Average FPS:", m_sysInfo.getAverageFps());

    m_sysInfo.preDraw();
    m_screen.draw();
    m_sysInfo.frameDrawn();
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:touch.view];
    float s = touch.view.contentScaleFactor;
    setDebugValue("W:", int(self.view.frame.size.width*s));
    setDebugValue("H:", int(self.view.frame.size.height*s));
    float xs = 2*640.0 / (self.view.frame.size.width * s);
    float ys = 2*960.0 / (self.view.frame.size.height * s);
    m_screen.touchDown(touchLocation.x*xs, touchLocation.y*ys);
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:touch.view];
    float s = touch.view.contentScaleFactor;
    float xs = 2*640.0 / (self.view.frame.size.width * s);
    float ys = 2*960.0 / (self.view.frame.size.height * s);
    m_screen.touchUp(touchLocation.x*xs, touchLocation.y*ys);
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:touch.view];
    float s = touch.view.contentScaleFactor;
    float xs = 2*640.0 / (self.view.frame.size.width * s);
    float ys = 2*960.0 / (self.view.frame.size.height * s);
    m_screen.touchMove(touchLocation.x*xs, touchLocation.y*ys);
}

@end
