	//
//  FourStreamsViewController.m
//  MiAlerts
//
//  Created by Mahammad on 10/3/14.
//  Copyright (c) 2014 Mahammad. All rights reserved.
//

#import "FourStreamsViewController.h"

#import "NetworkManager.h"

#include <CFNetwork/CFNetwork.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>



@interface FourStreamsViewController ()


// forward declarations
- (void)stopServer:(NSString *)reason;

@end

enum {
    kSendBufferSize = 32768
};

@implementation FourStreamsViewController
{
    uint8_t                     _buffer[kSendBufferSize];
}

@synthesize cams,mux_cams_urls0,mux_cams_urls1,mux_cams_urls2,mux_cams_urls3,urlConnection, bytes_read, timer_after_connect_before_receive, bytes_error, btnPing, btnInfo;

@synthesize networkStream = _networkStream;
@synthesize fileStream    = _fileStream;
@synthesize bufferOffset  = _bufferOffset;
@synthesize bufferLimit   = _bufferLimit;

@synthesize activityIndicator = _activityIndicator;

// for debug
//#define myNSLog NSLog

// for release
static const int bDebug = 0;
#define myNSLog3(x,y,z) { if(bDebug) NSLog(x,y,z);}
#define myNSLog2(x,y) { if(bDebug) NSLog(x,y);}
#define myNSLog1(x) { if(bDebug) NSLog(x);}

/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    
    
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}
/*
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
}
*/
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

//@end
- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    [self relayoutPics];
}

- (void)relayoutPics
{
    [self relayoutPic: @"1234"];
}

bool isContained(NSString* string, NSString* substring)
{
    NSRange range = [string rangeOfString:substring options:NSCaseInsensitiveSearch];
    return (range.location!=NSNotFound);
}

- (void)relayoutPic:(NSString*)idx
{
    CGRect viewBounds = self.view.bounds;
    
    
    if (UIDeviceOrientationIsLandscape([self interfaceOrientation]))
    {
        //x,y as you want
        //[ button setFrame:CGRectMake:(x,y,button.width,button.height)];

        
        int nHeight = viewBounds.size.height/2 - 5;
        int nWidth =  viewBounds.size.width/2 - 5;
        mCameraView1.frame = CGRectMake(viewBounds.origin.x,viewBounds.origin.y,nWidth,nHeight);
        mCameraView2.frame = CGRectMake(viewBounds.origin.x+nWidth,viewBounds.origin.y,nWidth,nHeight);
        mCameraView3.frame = CGRectMake(viewBounds.origin.x,viewBounds.origin.y+nHeight,nWidth,nHeight);
        mCameraView4.frame = CGRectMake(viewBounds.origin.x+nWidth,viewBounds.origin.y+nHeight,nWidth,nHeight);

        myNSLog2(@"Rect1: %@", NSStringFromCGRect(mCameraView1.frame));
        myNSLog2(@"Rect2: %@", NSStringFromCGRect(mCameraView2.frame));
        myNSLog2(@"Rect3: %@", NSStringFromCGRect(mCameraView3.frame));
        myNSLog2(@"Rect4: %@", NSStringFromCGRect(mCameraView4.frame));

        //[mCameraView1 ]
        
    }
    else
    {
        CGRect viewBounds = self.view.bounds;
        
        int nMargin = 3;
        int nXPadding = 0;//viewBounds.size.width/3;// 5;
        int nHeight = viewBounds.size.height/4;
        int nWidth =  (viewBounds.size.width-nXPadding-2*nMargin);
        
        
        if(isContained(idx, @"1")) mCameraView1.frame = CGRectMake(viewBounds.origin.x+nMargin,          viewBounds.origin.y+nMargin,nWidth,nHeight-nMargin);
        if(isContained(idx, @"2")) mCameraView2.frame = CGRectMake(viewBounds.origin.x+nMargin+nXPadding,viewBounds.origin.y+nMargin+nHeight,nWidth,nHeight-nMargin);
        if(isContained(idx, @"3")) mCameraView3.frame = CGRectMake(viewBounds.origin.x+nMargin,          viewBounds.origin.y+nMargin+2*nHeight,nWidth,nHeight-nMargin);
        if(isContained(idx, @"4")) mCameraView4.frame = CGRectMake(viewBounds.origin.x+nMargin+nXPadding,viewBounds.origin.y+nMargin+3*nHeight,nWidth,nHeight-nMargin);

    }
    
}

//static void *AVPlayerDemoCameraViewControllerStatusObservationContext = &AVPlayerDemoCameraViewControllerStatusObservationContext;
//@implementation AVFoundation_Test3ViewController
@synthesize mCameraView1, mCameraView2, mCameraView3, mCameraView4, BBBKID, timer_before_connect, timer_after_handshake, timer_after_successful_frame_received, frames_successful, frames_repeated;

- (void)dealloc
{
    NSLog(@"dealloc1");
//    [self stopServer:nil];
    [self closeStreams];
    //[self stopSendWithStatus:@"Stopped"];
    if(self.urlConnection != nil)
    {
        [self.urlConnection release];
        self.urlConnection = nil;
    }
    [super dealloc];
}

-(void)closeStreams
{
    myNSLog1(@"closeStreams");

    if(postBodyReadStream!=nil)
    {
        CFReadStreamClose(readStream);
        CFRelease(readStream);
        readStream = NULL;
        postBodyReadStream=nil;
    }
    if(postBodyWriteStream!=nil)
    {
        CFWriteStreamClose(writeStream);
        CFRelease(writeStream);
        writeStream = NULL;
        postBodyWriteStream=nil;
    }
    for(int cam=0; cam<4; cam++)
        if(new_image[cam]!=nil && new_image[cam]!=noSignalImage)
        {
            [new_image[cam] release];
            new_image[cam] = nil;
        }

    if(noSignalImage!=nil)
    {
        [noSignalImage release];
        noSignalImage=nil;
    }
}
- (void)viewDidLoad
{
    [super viewDidLoad];

    [self viewWillLayoutSubviews];
    //[self initStreamingVars];

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7)
    {
        self.edgesForExtendedLayout = UIRectEdgeNone;
    }
    
    self.activityIndicator.hidden = YES;
    staticBBBKID = [NSString stringWithString:BBBKID];

    /*for(int t=0;t<=4;t++)
        bCamsUpcated[t] = false;*/
[self initStreamingVars ];
    if([self bSockets])
    {
        [self performSelector:@selector(startSocketsStreaming) withObject:nil afterDelay:.2];
      //  [ self refreshALLCamera ];
    }
    else
    {
    [self relayoutPic: @"1234"];
    [self refreshAfterAWhile: @"1234"];
        
    /*[self refreshAfterAWhile: @"1"];
    [self refreshAfterAWhile: @"2"];
    [self refreshAfterAWhile: @"3"];
    [self refreshAfterAWhile: @"4"];*/
}
     [ self refreshALLCamera ];
    if([self bSockets])
    {
   //    [self startSocketsStreaming];
    }
    [self createInfoBarButton];
}

BOOL bCamsUpcated[5];
static CFReadStreamRef readStream = NULL;
NSOutputStream *postBodyWriteStream = NULL;
NSInputStream *postBodyReadStream = NULL;
CFWriteStreamRef writeStream;

-(void) startSocketsStreaming
{
    [self showProgress:@"Connecting to Server"];
    timer_before_connect = [self getTime];
    form = self;
    NSString *iHostname = [NSString stringWithFormat:@"50.62.46.121"];
    NSString *iPort = [NSString stringWithFormat:@"8080"];
    bCMDSent = false;

    static const CFOptionFlags kWriteNetworkEvents = kCFStreamEventEndEncountered |kCFStreamEventErrorOccurred |
                                                        kCFStreamEventCanAcceptBytes | kCFStreamEventOpenCompleted | kCFStreamEventNone;
    static const CFOptionFlags registeredEvents =    kCFStreamEventHasBytesAvailable | kCFStreamEventOpenCompleted | kCFStreamEventNone |
                                        kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;

    CFStreamClientContext ctxt = {0,(void*)self,NULL,NULL,NULL};
    CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault,(CFStringRef)iHostname);
    
    CFStreamCreatePairWithSocketToCFHost(kCFAllocatorDefault, hostRef, [iPort intValue],
                                         &readStream, &writeStream);
    CFRelease(hostRef);

    
    if(CFWriteStreamSetClient(writeStream, kWriteNetworkEvents, WriteStreamClientCallBack, &ctxt))
    {
        CFWriteStreamScheduleWithRunLoop(writeStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    }

    if (CFReadStreamSetClient(readStream, registeredEvents, myReadCallBack, &ctxt))
    {
        CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(),
                                        kCFRunLoopCommonModes);
    }
    postBodyWriteStream = writeStream;
    postBodyReadStream = readStream;

    [postBodyReadStream open];
    [postBodyWriteStream open];

   // [form sendCMDSocket:writeStream ];
}

-(void)setNoStreamNow: (int)cam
{
myNSLog2(@"setting no singal %d", cam);
if(new_image[cam]!=nil && new_image[cam]!=noSignalImage)
{
    [new_image[cam] release];
    new_image[cam] = nil;
}
new_image[cam]=noSignalImage;
bCamsUpcated[cam] = true;
}

-(void)setNoStream: (int)cam
{
   // NSImage
    nNoStream[cam]++;
    if(nNoStream[cam]>10)
    {
        if(noSignalImage!=nil && new_image[cam]!=noSignalImage)
        {
            [self setNoStreamNow: cam];
           /* myNSLog2(@"setting no singal %d", cam);
            if(new_image[cam]!=nil && new_image[cam]!=noSignalImage)
            {
                [new_image[cam] release];
                new_image[cam] = nil;
            }
            new_image[cam]=noSignalImage;
            bCamsUpcated[cam] = true;*/
        }
    }
};

UIImage* new_image[5], *noSignalImage;
int nNoStream[5],image_size_filter[5];
-(void)initStreamingVars
{
    noSignalImage = [UIImage imageNamed: @"orig_No-Signal-TV-320desktopia_net.jpg"]
                     ;
    for(int t= 0;t<4;t++)
    {
        nNoStream[t] = 0;
        image_size_filter[t] = -1;
        new_image[t] = nil;
        bCamsUpcated[t] = false;
        
    }
    bytes_error = timer_before_connect = timer_after_handshake = timer_after_successful_frame_received = frames_successful = frames_repeated = bytes_read = timer_after_connect_before_receive = 0;
    [self resetCounters];
}

-(NSString*)getTimeConsumed:(NSString*)title start:(long long)timer_start end:(long long)timer_end
{
    if(timer_start && timer_end && timer_end>=timer_start)
    {
        int msec = timer_end -  timer_start;
        if(msec>5000)
            return [NSString stringWithFormat:@"\n%@: \t%d s",title,msec/1000];
        else
            return [NSString stringWithFormat:@"\n%@: \t%d ms",title,msec];
    }
    
    return @"";
}

-(NSString*)addInfo:(NSString*)title info:(float)infoIN
{
    if(infoIN)
    {
        return [NSString stringWithFormat:@"\r%@: \t%.1f",title,infoIN];
    }
    
    return @"";
}


-(NSString*)addInfoI:(NSString*)title info:(int)infoIN
{
    if(infoIN)
    {
        return [NSString stringWithFormat:@"\r%@: \t%d",title,infoIN];
    }
    
    return @"";
}

-(NSString*)addInfoS:(NSString*)title info:(long long)infoIN
{
    if(infoIN)
    {
        if(infoIN<5000)
            return [NSString stringWithFormat:@"\r%@: \t%d bytes",title,(int)infoIN];
        else if(infoIN<5000000)
             return [NSString stringWithFormat:@"\r%@: \t%d kb",title,(int)infoIN/1024];
        else if(infoIN<5000000000)
            return [NSString stringWithFormat:@"\r%@: \t%d mb",title,(int)(infoIN/1024/1024)];
        else
            return [NSString stringWithFormat:@"\r%@: \t%d gb",title,(int)(infoIN/1024/1024/1024)];
    }
    
    return @"";
}

-(void)btnInfoAction
{
    NSString *info = nil;//@"No connected!";
    //if(timer_after_connect_before_receive)
    if([self bSockets])
        info = @"Server:\t50.62.46.121:8080";
    else
        info = @"Server:\thttp://www.theautoi.com/";
      //  info = @"!";
        
    info = [info stringByAppendingString:[self getTimeConsumed:@"Connection" start:timer_before_connect end:timer_after_connect_before_receive]];
    info = [info stringByAppendingString:[self getTimeConsumed:@"Handshake" start:timer_after_connect_before_receive end:timer_after_handshake]];
    info = [info stringByAppendingString:[self getTimeConsumed:@"First frame" start:timer_before_connect end:timer_after_successful_frame_received]];

    info = [info stringByAppendingString:[self addInfoI:@"Frames" info:frames_successful]];
    info = [info stringByAppendingString:[self addInfoI:@"Repeated" info:frames_repeated]];

    info = [info stringByAppendingString:[self addInfoS:@"Recevied" info:bytes_read]];
    info = [info stringByAppendingString:[self addInfoS:@"Errors" info:bytes_error]];

    long long time_for_frames = [self getTime] - timer_after_successful_frame_received;
    if(time_for_frames>0 && frames_successful)
    {
        float fps = (float)frames_successful*1000.f/(float)time_for_frames;
        info = [info stringByAppendingString:[self addInfo:@"FPS" info:fps]];
        
        float speed = (float)bytes_read*1000.f/(float)time_for_frames/1024.f;
        info = [info stringByAppendingString:[self addInfo:@"Speed (kb)" info:speed]];
    }
    myNSLog2( @"show info: %@", info );
    //return;
    if(HUD!=nil)
        [self endProgress];
    HUD = [[MBProgressHUD alloc]initWithView:self.view];
    HUD.delegate = self;
    HUD.mode = MBProgressHUDModeText;
    HUD.labelText = (timer_after_connect_before_receive?@"Connected":@"Not Connected");// @"Loading...";
    HUD.detailsLabelText = info;
    [self.navigationController.view.superview addSubview:HUD];
    HUD.removeFromSuperViewOnHide = YES;
    [HUD show:YES];
    [HUD hide:YES afterDelay:3];
    
 //   s = [s stringByAppendingString:newStr];
    
}

-(void)btnPingAction
{
    
}

-(void)createInfoBarButton
{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeInfoLight];
    [button addTarget:self action:@selector(btnInfoAction) forControlEvents:UIControlEventTouchUpInside];
    btnInfo = [[UIBarButtonItem alloc] initWithCustomView:button];
    
    //btnInfo = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(btnInfoAction)];
    btnPing = [[UIBarButtonItem alloc]initWithTitle:@"Ping" style:UIBarButtonItemStyleBordered target:self action:@selector(btnPingAction)];
    
    UIBarButtonItem *flex = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
    
    /* UIToolbar *iMapToolbar = [[UIToolbar alloc]init];
     [iMapToolbar setFrame:CGRectMake(0, 0, 100, 40)];
     [iMapToolbar setItems:[NSArray arrayWithObjects:flex,routeBBtn,flex,refreshBBtn,nil]];
     [iMapToolbar setBackgroundColor:[UIColor clearColor]];*/
    
    [self.navigationItem setRightBarButtonItems:[NSArray arrayWithObjects:flex,btnInfo/*,flex,btnPing,flex*/,nil]];
    [btnInfo release];
    [btnPing release];
}

static const bool bForceDecomressing = false;
-(void) setImage: (int)cam data:(UInt8*)data len:(int)length
{
    if(length<100)
    {
        myNSLog1(@"Invalid image data!");
        return;
    }
    if(image_size_filter[cam]==length)
    {
        myNSLog1(@"Same image data.. filtering out!");
        frames_repeated++;
        return;
    }

    NSData * byteData = [NSData dataWithBytes:data length:length];
    [self setImage: cam data:byteData];
}

-(BOOL) setImage: (int)cam data:(NSData*) byteData
{
    if(byteData==nil)
    {
        myNSLog1(@"Invalid image data!!");
        return FALSE;
    }
    if(image_size_filter[cam]==[byteData length])
    {
        myNSLog1(@"Same image data.. filtering out!");
        frames_repeated++;
        return FALSE;
    }

    UIImage *theImage = [[UIImage alloc] initWithData:byteData] ;
    if(theImage==nil)
    {
        myNSLog1(@"Invalid image interperated data!!!");
        return FALSE;
    }
    image_size_filter[cam]=[byteData length];
    myNSLog2(@"updating image buffer of cam %d", cam);
    bCamsUpcated[cam] = false;
    if(new_image[cam]!=nil && new_image[cam]!=noSignalImage)
    {
        [new_image[cam] release];
        new_image[cam] = nil;
    }
 
    if(bForceDecomressing)
    {
    CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData((CFDataRef)byteData);
    

    CGImageRef image = CGImageCreateWithJPEGDataProvider( imageDataProvider, NULL, NO, kCGRenderingIntentDefault);
    
    
    // Create a bitmap context from the image's specifications
    // (Note: We need to specify kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little
    // because PNGs are optimized by Xcode this way.)
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL, CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerComponent(image), CGImageGetWidth(image) * 4, colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
    
    
    // Draw the image into the bitmap context and retrieve the
    // decompressed image
    CGContextDrawImage(bitmapContext, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);
    
    CGImageRef decompressedImage = CGBitmapContextCreateImage(bitmapContext);
    
    
    // Create a UIImage
    new_image[cam] = [[UIImage alloc] initWithCGImage:decompressedImage];
    
    
    // Release everything
    CGImageRelease(decompressedImage);
    CGContextRelease(bitmapContext);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(image);
    CGDataProviderRelease(imageDataProvider);
}
    else
    {
        new_image[cam] = theImage;
       /* UIGraphicsBeginImageContext(CGSizeMake(100, 100)); // this isn't that important since you just want UIImage to decompress the image data before switching back to main thread
        [new_image[cam] drawAtPoint:CGPointZero];
        UIGraphicsEndImageContext();*/
    }
     myNSLog2(@"done updating image buffer of cam %d", cam);
    if(!form.timer_after_successful_frame_received)
        form.timer_after_successful_frame_received = [form getTime];
  
    bCamsUpcated[cam] = true;
    nNoStream[cam] = 0;
    frames_successful++;
    
    /*
    NSBitmapImageRep * imageRep = [NSBitmapImageRep imageRepWithData:byteData];
    NSSize imageSize = NSMakeSize(CGImageGetWidth([imageRep CGImage]), CGImageGetHeight([imageRep CGImage]));
    
    NSImage * image = [[NSImage alloc] initWithSize:imageSize];
    [image addRepresentation:imageRep];
*/
    return TRUE;
}

int handleBytes(char* buf, int bytesRead)
{
    myNSLog2(@"Received %d bytes!", bytesRead);
   
    int nZeroImages = 0;
    if(bytesRead<200)
    {
        myNSLog2(@"too short received message %d bytes!", bytesRead);
        return 4;
    }
    NSString* cmd = [NSString stringWithCString:buf length:200];
    
    if([cmd length]<4)
    {
        myNSLog2(@"too short command received  %@!", cmd);
        return 4;
    }
    if(![cmd hasPrefix:@"/"])
    {
        myNSLog2(@"Invalid command received  %@!", cmd);
        return 4;
    }
    
    if([cmd hasPrefix:@"/recstream4Jpegs"])
    {
        myNSLog2(@"Valid command received  %@!", cmd);
        int nImages_length[4] = {0,0,0,0};
        int nTotalSize = 0;
        for(int t=0; t<4;t++)
        {
            nImages_length[t] = [ form getURLParam: cmd param:[NSString stringWithFormat:@"l%d", t]];
            nTotalSize += nImages_length[t];
            
            if(nImages_length[t]==0)
                [form setNoStream: t];
        }
        if(nTotalSize==0)
        {
            myNSLog1(@"No images included.. nothing to do!");
            return 4;
        }
        int nAdd = 200;
        for(int t=0; t<4;t++)
        {
            if(nImages_length[t]==0)
            {
                nZeroImages++;
                continue;
            }
            [form setImage :t data:(UInt8*)(buf+nAdd) len:nImages_length[t]];

            nAdd += nImages_length[t];
        }
        return nZeroImages;
    }
    
    myNSLog2(@"Dont know how to handle the command received  %@!", cmd);
    return 4;
};

-(int)getURLParam: (NSString*)cmd param:(NSString*)param
{
    if(cmd!=nil && param!=nil)
    {
        NSRange range = [cmd rangeOfString:param options:NSCaseInsensitiveSearch];
        
        int nStart = range.location;
        
        if(nStart==NSNotFound)
            return 0;
        nStart += [param  length] +1;
      
        int nEnd = [[cmd substringFromIndex:nStart ] rangeOfString:@"&" options:NSCaseInsensitiveSearch ].location;
        
        if(nEnd==NSNotFound)
            nEnd = [cmd length]-1-nStart;
       
        
        if(nEnd<2)
            return 0;
        range.location = nStart;
         range.length = nEnd;
         NSString* paramString = [cmd substringWithRange:range];
        
        return [paramString intValue];
    }
    return 0;
};


static NSString* staticBBBKID;
static bool bCMDSent;
static FourStreamsViewController* form;
enum {
    BUFSIZE = 300000
};
static int nMsgLength = 0;
static int nRead = 0;
static UInt8 buf3[BUFSIZE];

-(void)resetConnection
{
    [self resetCounters];
};

-(void)resetCounters
{
    nMsgLength = 0;
    nRead = 0;
}

void myReadCallBack (CFReadStreamRef stream, CFStreamEventType event, void *myPtr) {
    myNSLog2(@"myReadCallBack: %lu", event);
    //[self getTime];, timer_before_connect1;
    
    switch(event) {
        case kCFStreamEventNone:
        {
            myNSLog1(@"Read Callback: Nothing is happening");
            break;
        }
        case kCFStreamEventOpenCompleted:
        {
            myNSLog1(@"Read Callback: Opened READ stream!");
            form.timer_after_connect_before_receive = [form getTime];//, timer_before_connect1;
            break;
        }

        case kCFStreamEventHasBytesAvailable:
            myNSLog1(@"Read Callback: kCFStreamEventHasBytesAvailable");
            if(readStream!=stream)
            {
                myNSLog1(@"Read Callback: Different read streams!!");
            }
            // It is safe to call CFReadStreamRead; it won’t block because bytes
            // are available.
            
            if (CFReadStreamHasBytesAvailable(readStream) )
            {
                int bytesRead =  0 ;
                int nTrails = 0;
                if(nMsgLength == 0)
                {
                    bytesRead = 0;
                    
                    while(bytesRead<12 && nTrails<50)
                    {
                        usleep(20000);
                        int read = CFReadStreamRead(readStream, buf3+bytesRead, 12-bytesRead);
                        if(read>0)
                            bytesRead += read;
                        else
                            usleep(200000);
                        nTrails++;
                    }
                    form.bytes_read += bytesRead;
                    if (bytesRead == 12) {
                        // check sign
                        //const UInt8 *rawstring = (const UInt8 *)[reqStr UTF8String];
                        //size_t length = strlen((const char *)rawstring);
                        //UInt8 buffertoSend[300];//(const UInt8 *)[reqStr UTF8String];
                        
                        long long sig = 0;//1234123456;
                        int nSizeofInt = sizeof(long long);
                        int cmd_length = 0;//200;
                        UInt8* pcmd_length = &cmd_length;
                        UInt8* psig = &sig;
                        
                        int nAddr = 0;
                        for(int t = 0; t<nSizeofInt; t++)
                        {
                            psig[nSizeofInt-1-t] = buf3[nAddr];
                            nAddr++;
                        }
                        
                        if ( sig == 1234123456 )
                        {
                            myNSLog1(@"Read Callback: correct signiture!!");
                            if(!form.timer_after_handshake)
                                form.timer_after_handshake = [form getTime];
                        }
                        else
                        {
                            myNSLog2(@"Read Callback: wrong signiture %lld.. resetting!!", sig );
                            form.bytes_error += bytesRead;
                            [form resetConnection];
                            return;
                        }
                        if(!form.timer_after_successful_frame_received)
                            [form endProgressWithMessage:@"Receiving.."];
                        
                        for(int t = 0; t<4; t++)
                        {
                            pcmd_length[4 - 1 - t] = buf3[nAddr];
                            nAddr++;
                        }
                        
                        if ( /*cmd_length>0 && */cmd_length >= 200 )
                        {
                            nMsgLength = cmd_length;
                            myNSLog2(@"Read Callback: correct buffer size: %d!!", nMsgLength);
                        }
                        else
                        {
                            myNSLog2(@"Read Callback: wrong signiture %d.. resetting!!", cmd_length );
                            form.bytes_error += bytesRead;
                            [form resetConnection];
                            return;
                        }
                        /*
                        for(int t = 0; t<200; t++)
                        {
                            if (length>nAddr)
                                buffertoSend[nAddr] = rawstring[t];
                            else
                                buffertoSend[nAddr] = 0;
                            nAddr++;
                        }
                        
*/
                        //ndleBytes(buf3, bytesRead);
                    }
                    else
                    {
                         myNSLog2(@"Read Callback: unhandled signiture reading case %d!!", bytesRead);
                        form.bytes_error += bytesRead;
                        break;
                    }
                }

                if(nMsgLength>=BUFSIZE)
                {
                    myNSLog1(@"Read Callback: message length overflow.. resetting!!");
                    [form resetConnection];
                    form.bytes_error += bytesRead;
                    return;
                }
                
                nTrails = 0;
                while ( nMsgLength > 0 && nRead<nMsgLength && nTrails<100)
                {
                    int nLeft = nMsgLength - nRead;
                    myNSLog3(@"Read Callback: trying to read: %d left of %d", nLeft, nMsgLength );
                    bytesRead = CFReadStreamRead(readStream, buf3+nRead, nLeft);
                    if(bytesRead>0)
                        nRead+=bytesRead;
                    else
                        usleep(20000);
                    nTrails++;
                }
                form.bytes_read += nRead;
                if( nMsgLength>0 && nRead==nMsgLength )
                {
                    long long start = CFAbsoluteTimeGetCurrent();//(long long)([[NSDate date] timeIntervalSince1970] * 1000.0) - start;
                    int nZeroImages = handleBytes(buf3, nRead);
                    long long milliseconds = CFAbsoluteTimeGetCurrent()- start;//(long long)([[NSDate date] timeIntervalSince1970] * 1000.0) - start;
                    myNSLog3(@"Buffer processing time %lld ms, zero cams are %d", milliseconds, nZeroImages);

     //               if(!form.timer_after_successful_frame_received)
        //                form.timer_after_successful_frame_received = [form getTime];
                    if(nZeroImages>0)
                         usleep(nZeroImages * 50000);
                    [form resetCounters];
                }
                else
                {
                    myNSLog3(@"Read Callback: read %d only of %d", nRead, nMsgLength );
                    usleep(20000);
                    form.bytes_error += nRead;
                }
            }
            if(![form isVisible])
                [form closeStreams];

            /*
            
            
                bytesRead = CFReadStreamRead(readStream, buf3, BUFSIZE);
                if (bytesRead > 0) {
                    handleBytes(buf3, bytesRead);
                }
            }
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            //  readStream
            int nTrils = 0;
            
            
            
            
            
            
            
            while(nTrils < 10 ||  bytesRead)
            {
               if (CFReadStreamHasBytesAvailable(readStream) )
                {
                    bytesRead = CFReadStreamRead(readStream, buf3, BUFSIZE);
                    if (bytesRead > 0) {
                        handleBytes(buf3, bytesRead);
                    }
                }
                else
                    usleep(100000);
                
                if(bytesRead>0 && nTrils++<10)
                    break;
                myNSLog2(@"Read Callback: kCFStreamEventHasBytesAvailable Waiting");
            }
                
/*
                int len = [stream read:buf maxLength:BUFSIZE];
                myNSLog2(@"server sent: %d bytes", len);
                if (len > 0) {
                    NSString *output = [[NSString alloc] initWithBytes:buf length:len encoding:NSASCIIStringEncoding];
                    
                    if (nil != output) {
                        myNSLog2(@"server said: %@", output);
                    }
                }*/
            

            myNSLog1(@"Read Callback: exit read loop");

            /*
            CFIndex bytesRead = CFReadStreamRead(stream, buf, BUFSIZE);
            if (bytesRead > 0) {
                handleBytes(buf, bytesRead);
            }*/
            // It is safe to ignore a value of bytesRead that is less than or
            // equal to zero because these cases will generate other events.
            break;
        case kCFStreamEventErrorOccurred:
            myNSLog1(@"Read Callback: kCFStreamEventErrorOccurred");
            CFStreamError error = CFReadStreamGetError(stream);
            myNSLog3(@"Connect error %s : %d", strerror(error.error), (error.error));
            //reportError(error);
            //[form endProgressWithMessage: @"Connection Error!"];
            CFReadStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(),
                                              kCFRunLoopCommonModes);
            CFReadStreamClose(stream);
            CFRelease(stream);
            [form endProgressWithMessage:@"Connection Error!"];
            if(!form.timer_after_handshake)
                form.timer_after_handshake = [form getTime];
            for(int t =0;t<4; t++)
                 [ form setNoStreamNow:t];
            break;
        case kCFStreamEventEndEncountered:
             myNSLog1(@"Read Callback: kCFStreamEventEndEncountered");
            if(!form.timer_after_handshake)
                form.timer_after_handshake = [form getTime];

            //reportCompletion();
            break;
            /*[form endProgressWithMessage:@"Done!"];
            CFReadStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(),
                                              kCFRunLoopCommonModes);
            CFReadStreamClose(stream);
            CFRelease(stream);
            break;*/
            default:
                myNSLog1(@"Read Callback default");
    }
}



 void WriteStreamClientCallBack( CFWriteStreamRef stream, CFStreamEventType type, void *clientCallBackInfo ) {
    myNSLog2(@"WriteStreamClientCallBack: %lu", type);
    switch (type)
    {
        case kCFStreamEventEndEncountered:
        {
            myNSLog1(@"Write Callback: Closing");
            CFWriteStreamClose(stream);
            CFRelease(stream);
            break;
        }
        case kCFStreamEventErrorOccurred:
        {
            myNSLog1(@"Write Callback: Crap, error!");
            CFStreamError error = CFReadStreamGetError(stream);
            myNSLog3(@"Write Callback: Connect error %s : %d", strerror(error.error), (int)(error.error));
            [form endProgressWithMessage:@"Connection Error!"];
            break;
        }
        case kCFStreamEventCanAcceptBytes:
        {
            myNSLog1(@"Write Callback: Stream can accept more bytes");
            if(bCMDSent)
            {
             //   myNSLog3(@"Write Callback: Closing this time");
//[postBodyWriteStream close];
                break;
            }
            
            [form showProgress:@"Sending.."];
            NSString *reqStr = [NSString stringWithFormat:@"/getstream4Jpegs?deviceid=%@&idx=0&ver=iPhone09Beta", staticBBBKID ];
            const UInt8 *rawstring = (const UInt8 *)[reqStr UTF8String];
            size_t length = strlen((const char *)rawstring);
            UInt8 buffertoSend[300];//(const UInt8 *)[reqStr UTF8String];
            
            long long sig = 1234123456;
            int nSizeofInt = sizeof(long long);
            int cmd_length = 200;
            UInt8* pcmd_length = &cmd_length;
            UInt8* psig = &sig;
            //CFWriteStreamWrite(stream, buffertoSend, 200/*strlen((char *)rawstring)*/);
            int nAddr = 0;
            for(int t = 0; t<nSizeofInt; t++)
            {
                buffertoSend[nAddr] = psig[nSizeofInt-1-t];
                nAddr++;
            }
            for(int t = 0; t<4; t++)
            {
                buffertoSend[nAddr] = pcmd_length[4 - 1 - t];
                nAddr++;
            }
            for(int t = 0; t<200; t++)
            {
                if (length>nAddr)
                    buffertoSend[nAddr] = rawstring[t];
                else
                    buffertoSend[nAddr] = 0;
                nAddr++;
            }
            
            CFWriteStreamWrite(stream, buffertoSend, nAddr/*strlen((char *)rawstring)*/);
            bCMDSent = true;
           // [stream close];
        }
            break;
        case kCFStreamEventNone:
        {
            myNSLog1(@"Write Callback: Nothing is happening");
            break;
        }
        case kCFStreamEventOpenCompleted:
        {
            myNSLog1(@"Write Callback: Opened WRITE stream!");
            break;
        }

        default:
             myNSLog1(@"Write Callback: Uknown event!");
    }
}

-(BOOL)isVisible
{
    UIViewController* topMostController = self.navigationController.visibleViewController;
    // NSString* topMostControllerName = [NSString stringWithFormat:@"%s", class_getName([topMostController class])];
    // myNSLog2( @"Visible Controller is %@", topMostControllerName);
    // if([topMostControllerName isEqualToString:@"MainMenuViewController"])
    
    if([topMostController isKindOfClass:[FourStreamsViewController class]])
    {
        //is topmost visible view controller
        return TRUE;
    }
    
    return false;
}

-(long long)getTime
{
    return CFAbsoluteTimeGetCurrent()*1000.f;
}

-(void)refreshALLCamera
{
    long long start = CFAbsoluteTimeGetCurrent();//(long long)([[NSDate date] timeIntervalSince1970] * 1000.0);
    
    if(![self isVisible] )
    {
        [self performSelector:@selector(refreshALLCamera) withObject:nil afterDelay:1];
        return;
    }

    
    //if(![self bSockets])
   //     return;
    bool bViewUpdated = false;
    for(int nIdx=1; nIdx<=4; nIdx++)
    {
        
  //      int nIdx = 1;
        UIImageView* mCameraView = mCameraView1;
        if(nIdx==2)
            mCameraView = mCameraView2;
        else if(nIdx==3)
            mCameraView = mCameraView3;
        else if(nIdx==4)
            mCameraView = mCameraView4;
        
            if(bCamsUpcated[nIdx-1])
            {
                myNSLog2(@"updating image %d", nIdx-1 );
                
                bCamsUpcated[nIdx-1] = false;
                @try
                {
                    if(new_image[nIdx-1]!=nil)
                    {
                         [mCameraView setImage:new_image[nIdx-1]];
                        bViewUpdated = true;
                    }
                }
                @catch (NSException *exception)
                {
                    
                    //This finds out which kind of exception it is.
                    myNSLog3(@"main: Caught %@: %@", [exception name], [exception reason]);
                }
               	
                myNSLog1(@"updating image end");
            }
            else
            {
                myNSLog2(@"Camera %d: no update needed",nIdx);
            }
        long long milliseconds = CFAbsoluteTimeGetCurrent()- start;//(long long)([[NSDate date] timeIntervalSince1970] * 1000.0) - start;
        myNSLog3(@"Camera %d image loading time: %lldms", nIdx, milliseconds);
    }
    
    if(bViewUpdated)
        [self relayoutPic:@"1234"];
    [self performSelector:@selector(refreshALLCamera) withObject:nil afterDelay:.6];
    
}
-(void)refreshCamera:(NSString*)idx
{
    long long start = CFAbsoluteTimeGetCurrent();//(long long)([[NSDate date] timeIntervalSince1970] * 1000.0);
   // return;
    //int nIdx = [idx intValue] - 1;

    BOOL bAccepted = FALSE;
    if([self isVisible])
    {

        int nIdx = 1;
        UIImageView* mCameraView = mCameraView1;
        if([idx isEqualToString:@"2"])
        {
            mCameraView = mCameraView2;
             nIdx = 2;
        }
        else if([idx isEqualToString:@"3"])
        {
            mCameraView = mCameraView3;
            nIdx = 3;
        }
        else if([idx isEqualToString:@"4"])
        {
            mCameraView = mCameraView4;
            nIdx = 4;
        }
        
        if([self bSockets])
        {
            if(bCamsUpcated[nIdx-1])
            {
                myNSLog2(@"updating image %d", nIdx-1 );
                
                bCamsUpcated[nIdx-1] = false;
                @try
                {
                    if(new_image[nIdx-1]!=nil)
                    {
                     /* 3 seconds
                        dispatch_async(dispatch_get_main_queue(), ^{
                             [mCameraView setImage:new_image[nIdx-1]];
                            NSLog(@"imageView set");
                        });
                        */
                        [mCameraView setImage:new_image[nIdx-1]];
                        [self relayoutPic:idx];
                        //mCameraView.hidden=YES;
                        /*
                        CGContextRef context = UIGraphicsGetCurrentContext();
                        CGContextSaveGState(context);
                        
                        CGAffineTransform t0 = CGContextGetCTM(context);
                        CGContextConcatCTM(context, t0);
                        
                        CGContextDrawImage(context, mCameraView.bounds, [new_image[nIdx-1] CGImage]);
                        CGContextRestoreGState(context);
                        * /
                        UIGraphicsBeginImageContext(CGSizeMake(100, 100)); // this isn't that important since you just want UIImage to decompress the image data before switching back to main thread
                        [new_image[nIdx-1] drawAtPoint:CGPointZero];
                        UIGraphicsEndImageContext();
                        
                        
                        //[new_image[nIdx-1] drawInRect:mCameraView.frame];
                        //CGContextRef context = UIGraphicsGetCurrentContext();
                        //[mCameraView  drawLayer:self.view.layer inContext:context];
                        
                        
                      //  self.view.animationImages = animationFramesArray;
                       // mCameraView.animationDuration = 10;
                        //[mCameraView startAnimating];
                        
                        //[mCameraView drawRect:mCameraView.frame];
                        //[new_image[nIdx-1] drawAtPoint:mCameraView.frame.origin];
                       // [mCameraView reloadInputViews];
                        //[[self view ]setNeedsDisplay];
                        /*
                        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW,
                                                                (int64_t)(0.005 * NSEC_PER_SEC));
                        dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
                            [[self view] setNeedsDisplay];
                        });*/
                    }
                }
                
                @catch (NSException *exception)
                {
                    
                    //This finds out which kind of exception it is.
                    myNSLog3(@"main: Caught %@: %@", [exception name], [exception reason]);
                    
                }
               	
                 myNSLog1(@"updating image end");
            }
            else
            {
                myNSLog2(@"Camera %@: no update needed",idx);
            }
        }
        else if([idx isEqualToString:@"1234"])
            for(nIdx=1; nIdx<=4;nIdx++)
        {
            NSString *ImageURL = [NSString stringWithFormat:@"http://50.62.46.121:85/%@/camera%d.jpeg", BBBKID, nIdx];
            myNSLog2(@"image url: %@", ImageURL);
            if(timer_before_connect==0)
                timer_before_connect=[self getTime];
            
            NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
       
            bAccepted = [self setImage: (int)(nIdx-1) data:imageData];
            
             if(imageData!=nil)
             {
                 if(timer_after_successful_frame_received==0)
                     timer_after_successful_frame_received = timer_after_handshake =[self getTime];

                int nImages_length=[imageData length];
                 bytes_read+=nImages_length;
                 if(nImages_length==0 || !bAccepted)
                     [self setNoStream: nIdx-1];
             }
            else
                [self setNoStream: nIdx-1];
        }
        else
        {
            NSString *ImageURL = [NSString stringWithFormat:@"http://50.62.46.121:85/%@/camera%@.jpeg", BBBKID, idx];
            myNSLog2(@"image url: %@", ImageURL);
            
            //@"http://www.infragistics.com/community/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/stevez/4274.UIViewContentModeScaleAspectFit.png";
            if(timer_before_connect==0)
                timer_before_connect=[self getTime];
            
            NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
            bAccepted = [self setImage: (int)(nIdx-1) data:imageData];
            
            if(imageData!=nil)
            {
                if(timer_after_successful_frame_received==0)
                    timer_after_successful_frame_received = timer_after_handshake =[self getTime];
                
                
                bytes_read+=[imageData length];
            }
            
            /*
             if(imageData!=nil)
             {
             mCameraView.image = [UIImage imageWithData:imageData];
             mCameraView.contentMode = UIViewContentModeScaleToFill;
             [mCameraView setNeedsDisplay];// .setNeedsDisplay = true;
             
             if(timer_after_successful_frame_received==0)
             timer_after_successful_frame_received = timer_after_handshake =[self getTime];
             
             frames_successful++;
             bytes_read+=[imageData length];
             
             
             
             [self relayoutPic:idx];
             }*/
        }

        long long milliseconds = CFAbsoluteTimeGetCurrent()- start;//(long long)([[NSDate date] timeIntervalSince1970] * 1000.0) - start;
        myNSLog3(@"Camera %@ image loading time: %lldms", idx, milliseconds);
        [ self refreshAfterAWhile: idx period:(bAccepted?1:3) ];
    }
    else
        myNSLog2(@"Camera %@ invisible",idx);
}

-(void)refreshAfterAWhile:(NSString*)idx
{
    [self refreshAfterAWhile:idx period:0.1];
}

-(void)refreshAfterAWhile:(NSString*)idx period:(double)period
{
    if(period<0.1)
        period=0.1;
    
    [self performSelector:@selector(refreshCamera:) withObject:idx afterDelay:period];
}

- (void)observeValueForKeyPath:(NSString*) path ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{

   /*
    if(object == mPlayer1)
    if (mPlayer1.status == AVPlayerStatusReadyToPlay) {
        [self.mCameraView1 setPlayer:self.mPlayer1];
        [self.mPlayer1 play];
    }
 
    if(object == mPlayer2)
        if (mPlayer2.status == AVPlayerStatusReadyToPlay) {
        [self.mCameraView2 setPlayer:self.mPlayer2];
        [self.mPlayer2 play];
    }
 
    if(object == mPlayer3)
        if (mPlayer3.status == AVPlayerStatusReadyToPlay) {
        [self.mCameraView3 setPlayer:self.mPlayer3];
        [self.mPlayer3 play];
    }
 
    if(object == mPlayer4)
        if (mPlayer4.status == AVPlayerStatusReadyToPlay) {
        [self.mCameraView4 setPlayer:self.mPlayer4];
        [self.mPlayer4 play];
    }*/
    
    CGRect viewBounds = self.view.bounds;
   
    int nMargin = 3;
    int nXPadding = 0;//viewBounds.size.width/3;// 5;
    int nHeight = viewBounds.size.height/4;
    int nWidth =  (viewBounds.size.width-nXPadding-2*nMargin);
 
    
    mCameraView1.frame = CGRectMake(viewBounds.origin.x+nMargin,          viewBounds.origin.y+nMargin,nWidth,nHeight-nMargin);
    mCameraView2.frame = CGRectMake(viewBounds.origin.x+nMargin+nXPadding,viewBounds.origin.y+nMargin+nHeight,nWidth,nHeight-nMargin);
    mCameraView3.frame = CGRectMake(viewBounds.origin.x+nMargin,          viewBounds.origin.y+nMargin+2*nHeight,nWidth,nHeight-nMargin);
    mCameraView4.frame = CGRectMake(viewBounds.origin.x+nMargin+nXPadding,viewBounds.origin.y+nMargin+3*nHeight,nWidth,nHeight-nMargin);
 /*
    [ mCameraView1 setVideoFillMode:AVLayerVideoGravityResize];
    [ mCameraView2 setVideoFillMode:AVLayerVideoGravityResize];
    [ mCameraView3 setVideoFillMode:AVLayerVideoGravityResize];
    [ mCameraView4 setVideoFillMode:AVLayerVideoGravityResize];
    */
    
    myNSLog2(@"Rect1: %@", NSStringFromCGRect(mCameraView1.frame));
    myNSLog2(@"Rect2: %@", NSStringFromCGRect(mCameraView2.frame));
    myNSLog2(@"Rect3: %@", NSStringFromCGRect(mCameraView3.frame));
}

-(void) showProgress: (NSString*) job
{
    myNSLog2( @"show Progress: %@", job );
   //return;
    if(HUD!=nil)
        [self endProgress];
    HUD = [[MBProgressHUD alloc]initWithView:self.view];
    HUD.delegate = self;
    HUD.mode = MBProgressHUDModeText;
    HUD.labelText = job;// @"Loading...";
    [self.navigationController.view.superview addSubview:HUD];
    
    [HUD show:YES];
    
}

- (void)stopServer:(NSString *)reason
{
    [ self endProgressWithMessage:reason];
}

-(void) endProgress
{
    if(HUD!=nil)
    {
        [HUD hide:YES afterDelay:0.3];
        [HUD removeFromSuperview];
        HUD = nil;
    }
}

-(void) endProgressWithMessage: (NSString*) msg
{
    myNSLog2( @"end Progress: %@", msg );

    if(HUD!=nil)
    {
        HUD.labelText = msg;
        HUD.removeFromSuperViewOnHide = YES;
        [HUD hide:YES afterDelay:3];
        HUD = nil;
    }
}





























#pragma mark * Status management

// These methods are used by the core transfer code to update the UI.

- (void)sendDidStart
{
    [self showProgress: @"Sending"];
  //  self.cancelButton.enabled = YES;
    [self.activityIndicator startAnimating];
    [[NetworkManager sharedInstance] didStartNetworkOperation];
}

- (void)updateStatus:(NSString *)statusString
{
    assert(statusString != nil);
    [self showProgress:statusString];

   // self.statusLabel.text = statusString;
}

- (void)sendDidStopWithStatus:(NSString *)statusString
{
    if (statusString == nil) {
        statusString = @"Send succeeded";
    }
        [self showProgress:statusString]; //self.statusLabel.text = statusString;
   // self.cancelButton.enabled = NO;
    [self.activityIndicator stopAnimating];
    [[NetworkManager sharedInstance] didStopNetworkOperation];
}

#pragma mark * Core transfer code

// This is the code that actually does the networking.

// Because buffer is declared as an array, you have to use a custom getter.
// A synthesised getter doesn't compile.

- (uint8_t *)buffer
{
    return self->_buffer;
}

- (BOOL)isSending
{
    return (self.networkStream != nil);
}
/*
- (void)startSend:(NSString *)filePath
{
    NSOutputStream *    output;
    BOOL                success;
    NSNetService *      netService;
    
    assert(filePath != nil);
    
    assert(self.networkStream == nil);      // don't tap send twice in a row!
    assert(self.fileStream == nil);         // ditto
    
    // Open a stream for the file we're going to send.
    
    self.fileStream = [NSInputStream inputStreamWithFileAtPath:filePath];
    assert(self.fileStream != nil);
    
    [self.fileStream open];
    
    // Open a stream to the server, finding the server via Bonjour.  Then configure
    // the stream for async operation.
    
    netService = [[NSNetService alloc] initWithDomain:@"local." type:@"_x-SNSUpload._tcp." name:@"Test"];
    assert(netService != nil);
    
    // Until <rdar://problem/6868813> is fixed, we have to use our own code to open the streams
    // rather than call -[NSNetService getInputStream:outputStream:].  See the comments in
    // QNetworkAdditions.m for the details.
    
    success = [netService qNetworkAdditions_getInputStream:NULL outputStream:&output];
    assert(success);
    
    self.networkStream = output;
    self.networkStream.delegate = self;
    [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    
    [self.networkStream open];
    
    // Tell the UI we're sending.
    
    [self sendDidStart];
}
* /
- (void)stopSendWithStatus:(NSString *)statusString
{
    if (self.networkStream != nil) {
        self.networkStream.delegate = nil;
        [self.networkStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [self.networkStream close];
        self.networkStream = nil;
    }
    if (self.fileStream != nil) {
        [self.fileStream close];
        self.fileStream = nil;
    }
    self.bufferOffset = 0;
    self.bufferLimit  = 0;
    [self sendDidStopWithStatus:statusString];
}
/*
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
// An NSStream delegate callback that's called when events happen on our
// network stream.
{
    assert(aStream == self.networkStream);
#pragma unused(aStream)
    
    switch (eventCode) {
        case NSStreamEventOpenCompleted: {
            [self updateStatus:@"Opened connection"];
        } break;
        case NSStreamEventHasBytesAvailable: {
            assert(NO);     // should never happen for the output stream
        } break;
        case NSStreamEventHasSpaceAvailable: {
            [self updateStatus:@"Sending"];
            
            // If we don't have any data buffered, go read the next chunk of data.
            
            if (self.bufferOffset == self.bufferLimit) {
                NSInteger   bytesRead;
                
                bytesRead = [self.fileStream read:self.buffer maxLength:kSendBufferSize];
                
                if (bytesRead == -1) {
                    [self stopSendWithStatus:@"File read error"];
                } else if (bytesRead == 0) {
                    [self stopSendWithStatus:nil];
                } else {
                    self.bufferOffset = 0;
                    self.bufferLimit  = bytesRead;
                }
            }
            
            // If we're not out of data completely, send the next chunk.
            
            if (self.bufferOffset != self.bufferLimit) {
                NSInteger   bytesWritten;
                
                bytesWritten = [self.networkStream write:&self.buffer[self.bufferOffset] maxLength:self.bufferLimit - self.bufferOffset];
                assert(bytesWritten != 0);
                if (bytesWritten == -1) {
                    [self stopSendWithStatus:@"Network write error"];
                } else {
                    self.bufferOffset += bytesWritten;
                }
            }
        } break;
        case NSStreamEventErrorOccurred: {
            [self stopSendWithStatus:@"Stream open error"];
        } break;
        case NSStreamEventEndEncountered: {
            // ignore
        } break;
        default: {
            assert(NO);
        } break;
    }
}*/

#pragma mark * Actions
/*
- (IBAction)sendAction:(UIView *)sender
{
    assert( [sender isKindOfClass:[UIView class]] );
    
    if ( ! self.isSending ) {
        NSString *  filePath;
        
        // Use the tag on the button to determine which image to send.
        
        filePath = [[NetworkManager sharedInstance] pathForTestImage:sender.tag];
        assert(filePath != nil);
        
        [self startSend:filePath];
    }
}
* /

- (IBAction)cancelAction:(id)sender
{
#pragma unused(sender)
    [self stopSendWithStatus:@"Cancelled"];
}
*/
#pragma mark * View controller boilerplate

- (void)viewDidDisappear
{
    myNSLog1(@"viewDidDisappear");
    
    [self closeStreams];
    //[super viewDidDisappear];
   // self.statusLabel = nil;
    self.activityIndicator = nil;
  //  self.cancelButton = nil;
}

-(void) notifyWatching
{
        BOOL isInternetAvailable = [UIAPPDELEGATE isInternetAvailable];
        
        if(isInternetAvailable == FALSE)
        {// TODO: change this to hud
            /* UIAlertView *connAlert = [[UIAlertView alloc]initWithTitle:@"Connection Alert" message:@"Please check internet connection" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
             [connAlert show];
             [connAlert release];
             
             */
            MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
            
            hud.mode = MBProgressHUDModeText;
            hud.labelText = @"Please check internet connection!";
            hud.margin = 10.f;
            hud.yOffset = 150.f;
            hud.removeFromSuperViewOnHide = YES;
            
            [hud hide:YES afterDelay:3];
            
            return;
        }
        if(HUD!=NULL)
        {// change this to hud
            
            HUD.labelText = @"Please wait!";
            return;
        }
        
        [ self showProgress: @"Connecting"];
        
        //    NSString *deviceId = [[UIDevice currentDevice]uniqueIdentifier];
        //http://www.theautoi.com/request_manual_video.php?username=whiletrue@hotmail.com&password=12
        NSString *deviceId = [[[[UIDevice currentDevice] identifierForVendor] UUIDString] autorelease];
    cams=4;
        NSString *loginUrl = [[NSString stringWithFormat:@"http://www.theautoi.com/listDevices.php?username=%@&password=%@&token=%@&deviceid=%@&cams=%@", UIAPPDELEGATE.loggedUserName, UIAPPDELEGATE.loggedPassword,UIAPPDELEGATE.dToken,deviceId,cams] autorelease];
        
        NSURL *url = [NSURL URLWithString:loginUrl];
        NSMutableURLRequest *urlRequest = [[[NSMutableURLRequest alloc]initWithURL:url]autorelease];
        myNSLog2(@"RequestSreamingVideo Url=%@" , loginUrl);
        
        if(self.urlConnection != nil)
        {
            [self.urlConnection release];
            self.urlConnection = nil;
        }
        if(self.mutableData !=nil)
        {
            self.mutableData = nil;
        }
        self.mutableData = [NSMutableData data];
        
        self.urlConnection = [[NSURLConnection alloc]initWithRequest:urlRequest delegate:self];
        [self.urlConnection setAccessibilityHint:@"Devices List"];
}


- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    //
    /* if(connection!=nil && [[connection accessibilityHint] isEqualToString:@"GetVideos"] )
     {
     [self.mutableDataVideos setLength:0];
     }
     else */ if(connection!=nil && [[connection accessibilityHint] isEqualToString:@"Devices List"] )
     {
         [self.mutableData setLength:0];
     }
     else
         [self.mutableData setLength:0];
}


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    /*if(connection!=nil && [[connection accessibilityHint] isEqualToString:@"GetVideos"] )
     {
     [self.mutableDataVideos appendData:data];
     }
     else */ if(connection!=nil && [[connection accessibilityHint] isEqualToString:@"Devices List"] )
     {
         [self.mutableData appendData:data];
     }
     else
         [self.mutableData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    myNSLog1(@"error3");
    [self endProgressWithMessage:@"Request Error"];
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSString *response = nil;//[[NSString alloc]initWithData:self.mutableData encoding:NSASCIIStringEncoding];
    if(connection!=nil && [[connection accessibilityHint] isEqualToString:@"GetVideos"] )
    {
      //  response = [[NSString alloc]initWithData:self.mutableDataVideos encoding:NSASCIIStringEncoding];
    }
    else
        response = [[NSString alloc]initWithData:self.mutableData encoding:NSASCIIStringEncoding];
    
    // myNSLog2(@"the response is %@",response);
    //if([connection.accessibilityHint isEqualToString:@"Login"])
    if(connection!=nil)
    {/*
      if([[connection accessibilityHint] isEqualToString:@"GetVideos"] )
      {
      [self parseVideosResponse:response :connection];
      if(UIAPPDELEGATE.isAutoUpdate)
      [self callWSAfterAWhile];
      }
      else if([[connection accessibilityHint] isEqualToString:@"User Video"] )
      [self parseUserVideoResponse:response];
      else */
        if(connection!=nil && [[connection accessibilityHint] isEqualToString:@"Devices List"] )
        {
            [self parseDevicesResponse:response];
        }
        else
            myNSLog2(@"unknown response received: %@", [connection accessibilityHint] );
    }
}

-(void) parseDevicesResponse:(NSString *)response
{
    myNSLog2(@"the Devices response is %@",response);
    if([response rangeOfString:@"success"].location != NSNotFound)
    {
        myNSLog1(@"Report watching succeeded!");
    }
    else if([response rangeOfString:@"already"].location != NSNotFound)
    {
        [self endProgressWithMessage:@"Handling previous request"];
    }
    else if([response rangeOfString:@"error"].location != NSNotFound)
    {
        [self endProgressWithMessage:@"Error requesting a stream!"];
        return;
    }
    else
        [self endProgress];
}

@end